| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef COMPONENTS_SAFE_BROWSING_CONTENT_TRIGGERS_SUSPICIOUS_SITE_TRIGGER_H_ |
| #define COMPONENTS_SAFE_BROWSING_CONTENT_TRIGGERS_SUSPICIOUS_SITE_TRIGGER_H_ |
| |
| #include "base/macros.h" |
| #include "base/memory/weak_ptr.h" |
| #include "content/public/browser/web_contents_observer.h" |
| #include "content/public/browser/web_contents_user_data.h" |
| |
| class PrefService; |
| |
| namespace history { |
| class HistoryService; |
| } |
| |
| namespace network { |
| class SharedURLLoaderFactory; |
| } // namespace network |
| |
| namespace safe_browsing { |
| class TriggerManager; |
| |
| // Metric for tracking what the Suspicious Site trigger does on each event. |
| extern const char kSuspiciousSiteTriggerEventMetricName[]; |
| |
| // Metric for tracking how often reports from this trigger are rejected by the |
| // trigger manager, and for what reason. |
| extern const char kSuspiciousSiteTriggerReportRejectionMetricName[]; |
| |
| // Metric for tracking the state of the trigger when the report delay timer |
| // fires. |
| extern const char kSuspiciousSiteTriggerReportDelayStateMetricName[]; |
| |
| // Tracks events this trigger listens for or actions it performs. These values |
| // are written to logs. New enum values can be added, but existing enums must |
| // never be renumbered or deleted and reused. |
| enum class SuspiciousSiteTriggerEvent { |
| // A page load started. |
| PAGE_LOAD_START = 0, |
| // A page load finished. |
| PAGE_LOAD_FINISH = 1, |
| // A suspicious site was detected. |
| SUSPICIOUS_SITE_DETECTED = 2, |
| // The report delay timer fired. |
| REPORT_DELAY_TIMER = 3, |
| // A suspicious site report was started. |
| REPORT_STARTED = 4, |
| // A suspicious site report was created and sent. |
| REPORT_FINISHED = 5, |
| // The trigger was waiting for a load to finish before creating a report but |
| // a new load started before the previous load could finish, so the report |
| // was cancelled. |
| PENDING_REPORT_CANCELLED_BY_LOAD = 6, |
| // The trigger tried to start the report but it was rejected by the trigger |
| // manager. |
| REPORT_START_FAILED = 7, |
| // The trigger tried to finish the report but it was rejected by the trigger |
| // manager. |
| REPORT_FINISH_FAILED = 8, |
| // The trigger could have sent a report but it was skipped, typically because |
| // the trigger was out of quota. |
| REPORT_POSSIBLE_BUT_SKIPPED = 9, |
| // New events must be added before kMaxValue, and the value of kMaxValue |
| // updated. |
| kMaxValue = REPORT_POSSIBLE_BUT_SKIPPED |
| }; |
| |
| // Notify a suspicious site trigger on a particular tab that a suspicious site |
| // was detected. |web_contents_getter| specifies the tab where the site was |
| // detected. |
| // Must be called on UI thread. |
| void NotifySuspiciousSiteTriggerDetected( |
| const base::RepeatingCallback<content::WebContents*()>& |
| web_contents_getter); |
| |
| // This class watches tab-level events such as the start and end of a page |
| // load, and also listens for events from the SuspiciousSiteURLThrottle that |
| // indicate there was a hit on the suspicious site list. This trigger is |
| // repsonsible for creating reports about the page at the right time, based on |
| // the sequence of such events. |
| class SuspiciousSiteTrigger |
| : public content::WebContentsObserver, |
| public content::WebContentsUserData<SuspiciousSiteTrigger> { |
| public: |
| // The different states the trigger could be in. |
| // These values are written to logs. New enum values can be added, but |
| // existing enums must never be renumbered or deleted and reused. |
| enum class TriggerState { |
| // Trigger is idle, page is not loading, no report requested. |
| IDLE = 0, |
| // Page load has started, no report requested. |
| LOADING = 1, |
| // Page load has started and a report is requested. The report will be |
| // created when the page load finishes. |
| LOADING_WILL_REPORT = 2, |
| // A page load finished and a report for the page has started. |
| REPORT_STARTED = 3, |
| // The trigger is in monitoring mode where it listens for events and |
| // increments some metrics but never sends reports. The trigger will never |
| // leave this state. |
| MONITOR_MODE = 4, |
| // New states must be added before kMaxValue and the value of kMaxValue |
| // updated. |
| kMaxValue = MONITOR_MODE |
| }; |
| |
| ~SuspiciousSiteTrigger() override; |
| |
| static void CreateForWebContents( |
| content::WebContents* web_contents, |
| TriggerManager* trigger_manager, |
| PrefService* prefs, |
| scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, |
| history::HistoryService* history_service, |
| bool monitor_mode); |
| |
| // content::WebContentsObserver implementations. |
| void DidStartLoading() override; |
| void DidStopLoading() override; |
| |
| // Called when a suspicious site has been detected on the tab that this |
| // trigger is running on. |
| void SuspiciousSiteDetected(); |
| |
| private: |
| friend class content::WebContentsUserData<SuspiciousSiteTrigger>; |
| friend class SuspiciousSiteTriggerTest; |
| |
| SuspiciousSiteTrigger( |
| content::WebContents* web_contents, |
| TriggerManager* trigger_manager, |
| PrefService* prefs, |
| scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, |
| history::HistoryService* history_service, |
| bool monitor_mode); |
| |
| // Tries to start a report. Returns whether a report started successfully. |
| // If a report is started, a delayed callback will also begin to notify |
| // the trigger when the report should be completed and sent. |
| bool MaybeStartReport(); |
| |
| // Calls into the trigger manager to finish the active report and send it. |
| void FinishReport(); |
| |
| // Called when a suspicious site is detected while in monitor mode. We update |
| // metrics if we determine that a report could have been sent had the trigger |
| // been active. |
| void SuspiciousSiteDetectedWhenMonitoring(); |
| |
| // Called when the report delay timer fires, indicating that the active |
| // report should be completed and sent. |
| void ReportDelayTimerFired(); |
| |
| // Sets a task runner to use for tests. |
| void SetTaskRunnerForTest( |
| scoped_refptr<base::SingleThreadTaskRunner> task_runner); |
| |
| // The delay (in milliseconds) to wait before finishing a report. Can be |
| // overwritten for tests. |
| int64_t finish_report_delay_ms_; |
| |
| // Current state of the trigger. Used to synchronize page load events with |
| // suspicious site list hit events so that reports can be generated at the |
| // right time. |
| TriggerState current_state_; |
| |
| // TriggerManager gets called if this trigger detects a suspicious site and |
| // wants to collect data abou tit. Not owned. |
| TriggerManager* trigger_manager_; |
| |
| PrefService* prefs_; |
| scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; |
| history::HistoryService* history_service_; |
| |
| // Task runner for posting delayed tasks. Normally set to the runner for the |
| // UI thread, but can be overwritten for tests. |
| scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| |
| base::WeakPtrFactory<SuspiciousSiteTrigger> weak_ptr_factory_{this}; |
| |
| WEB_CONTENTS_USER_DATA_KEY_DECL(); |
| |
| DISALLOW_COPY_AND_ASSIGN(SuspiciousSiteTrigger); |
| }; |
| |
| } // namespace safe_browsing |
| |
| #endif // COMPONENTS_SAFE_BROWSING_CONTENT_TRIGGERS_SUSPICIOUS_SITE_TRIGGER_H_ |