| // 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_SAFE_BROWSING_TELEMETRY_ANDROID_ANDROID_TELEMETRY_SERVICE_H_ |
| #define CHROME_BROWSER_SAFE_BROWSING_TELEMETRY_ANDROID_ANDROID_TELEMETRY_SERVICE_H_ |
| |
| #include <memory> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "chrome/browser/safe_browsing/telemetry/telemetry_service.h" |
| #include "components/download/public/common/download_item.h" |
| #include "components/download/public/common/simple_download_manager_coordinator.h" |
| #include "components/safe_browsing/android/safe_browsing_api_handler_util.h" |
| #include "components/safe_browsing/content/browser/safe_browsing_navigation_observer_manager.h" |
| #include "components/safe_browsing/core/common/proto/csd.pb.h" |
| #include "content/public/browser/browser_context.h" |
| #include "content/public/browser/download_manager.h" |
| |
| class Profile; |
| class PrefService; |
| |
| namespace safe_browsing { |
| |
| // Enumerates the possibilities for whether the CSBRR report was sent (or not). |
| enum class ApkDownloadTelemetryOutcome { |
| NOT_SENT_SAFE_BROWSING_NOT_ENABLED = 0, |
| // |web_contents| was nullptr. This happens sometimes when downloads are |
| // resumed but it's not clear exactly when. |
| NOT_SENT_MISSING_WEB_CONTENTS = 1, |
| // No ping sent because the user is in Incognito mode. |
| NOT_SENT_INCOGNITO = 2, |
| // No ping sent because the user hasn't enabled extended reporting. |
| // Deprecated for NOT_SENT_UNCONSENTED. |
| NOT_SENT_EXTENDED_REPORTING_DISABLED = 3, |
| // Download was cancelled. |
| NOT_SENT_DOWNLOAD_CANCELLED = 4, |
| // Failed to serialize the report. |
| NOT_SENT_FAILED_TO_SERIALIZE = 5, |
| // Feature not enabled so don't send. |
| NOT_SENT_FEATURE_NOT_ENABLED = 6, |
| // Download completed. Ping sent. |
| SENT = 7, |
| // No ping sent because the user hasn't enabled enhanced protection and |
| // extended reporting. |
| NOT_SENT_UNCONSENTED = 8, |
| kMaxValue = NOT_SENT_UNCONSENTED |
| }; |
| |
| // This class is used to send telemetry information to Safe Browsing for |
| // security related incidents. The information is sent only if: |
| // 1. The user has opted in to extended reporting, AND |
| // 2. The security incident did not happen in an incognito window. |
| // As the name suggests, this works only on Android. |
| |
| // The following events are currently considered security related incidents from |
| // the perspective of this class: |
| // 1. Downloading off-market APKs. See: go/zurkon-v1-referrer-dd |
| |
| class AndroidTelemetryService |
| : public download::DownloadItem::Observer, |
| public download::SimpleDownloadManagerCoordinator::Observer, |
| public TelemetryService { |
| public: |
| explicit AndroidTelemetryService(Profile* profile); |
| |
| AndroidTelemetryService(const AndroidTelemetryService&) = delete; |
| AndroidTelemetryService& operator=(const AndroidTelemetryService&) = delete; |
| |
| ~AndroidTelemetryService() override; |
| |
| // download::SimpleDownloadManagerCoordinator::Observer. |
| void OnDownloadCreated(download::DownloadItem* item) override; |
| |
| // download::DownloadItem::Observer. |
| void OnDownloadUpdated(download::DownloadItem* item) override; |
| void OnDownloadRemoved(download::DownloadItem* item) override; |
| |
| Profile* profile() { return profile_; } |
| |
| private: |
| friend class AndroidTelemetryServiceTest; |
| |
| using OnGetReportDoneCallback = base::OnceCallback<void( |
| std::unique_ptr<ClientSafeBrowsingReportRequest>)>; |
| |
| enum class ApkDownloadTelemetryIncompleteReason { |
| // |web_contents| was nullptr. This happens sometimes when downloads are |
| // resumed but it's not clear exactly when. |
| MISSING_WEB_CONTENTS = 0, |
| // Navigation manager wasn't ready yet to provide the referrer chain. |
| SB_NAVIGATION_MANAGER_NOT_READY = 1, |
| // Full referrer chain captured. |
| COMPLETE = 2, |
| // No render frame host existed for the download |
| MISSING_RENDER_FRAME_HOST = 3, |
| // The render frame host had not committed to a valid URL |
| RENDER_FRAME_HOST_INVALID_URL = 4, |
| |
| kMaxValue = RENDER_FRAME_HOST_INVALID_URL, |
| }; |
| |
| struct ReferrerChainResult { |
| ApkDownloadTelemetryIncompleteReason missing_reason; |
| SafeBrowsingNavigationObserverManager::AttributionResult result; |
| bool triggered_by_intent = false; |
| }; |
| |
| // Whether the ping can be sent, based on empty web_contents, or incognito |
| // mode, or extended reporting opt-in status, |
| bool CanSendPing(download::DownloadItem* item); |
| |
| // Populates the `ReferrerChainData` on `item` so that we can use it during |
| // report construction. |
| void FillReferrerChain(download::DownloadItem* item); |
| |
| // Sets the relevant fields in an instance of |
| // |ClientSafeBrowsingReportRequest| proto and returns that proto |
| // asynchronously. |
| void GetReport(download::DownloadItem* item, |
| OnGetReportDoneCallback callback); |
| |
| // Callback when we know if app verification is enabled. |
| void IsVerifyAppsEnabled( |
| std::unique_ptr<ClientSafeBrowsingReportRequest> report, |
| OnGetReportDoneCallback callback, |
| VerifyAppsEnabledResult result); |
| |
| // Callback when report generation is complete. |
| void OnGetReportDone(download::DownloadItem* item, |
| std::unique_ptr<ClientSafeBrowsingReportRequest> report); |
| |
| // Sends |report| proto to the Safe Browsing backend. The report may not be |
| // sent if the proto fails to serialize. |
| void MaybeSendApkDownloadReport( |
| content::BrowserContext* browser_context, |
| std::unique_ptr<ClientSafeBrowsingReportRequest> report); |
| |
| // Helper method to get prefs from |profile_|. |
| const PrefService* GetPrefs(); |
| |
| // Profile associated with this instance. Unowned. |
| raw_ptr<Profile> profile_; |
| |
| // Referrer chains are best computed at download start, before we |
| // know whether it will be suitable to send a ping. In order to log |
| // metrics only for downloads that send a ping, we persist the |
| // outcome of referrer chain computation. |
| std::map<download::DownloadItem*, ReferrerChainResult> referrer_chain_result_; |
| |
| // The collection of `DownloadItem`s we're currently collecting reports for. |
| std::set<download::DownloadItem*> reports_in_progress_; |
| |
| base::WeakPtrFactory<AndroidTelemetryService> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace safe_browsing |
| |
| #endif // CHROME_BROWSER_SAFE_BROWSING_TELEMETRY_ANDROID_ANDROID_TELEMETRY_SERVICE_H_ |