// Copyright 2015 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. #include "chrome/browser/safe_browsing/unverified_download_policy.h" #include "base/bind.h" #include "base/callback.h" #include "base/files/file_path.h" #include "base/metrics/sparse_histogram.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/safe_browsing/unverified_download_field_trial.h" #include "chrome/common/safe_browsing/download_protection_util.h" #include "components/rappor/rappor_service.h" #include "components/rappor/rappor_utils.h" #include "components/safe_browsing_db/database_manager.h" #include "content/public/browser/browser_thread.h" namespace safe_browsing { namespace { using content::BrowserThread; // Record the uma_file_type to UMA as an enum, and the URL's eTLD+1 to Rappor. void RecordPolicyMetricOnUIThread(const std::string& metric_name, int uma_file_type, const GURL& requestor) { DCHECK_CURRENTLY_ON(BrowserThread::UI); UMA_HISTOGRAM_SPARSE_SLOWLY(metric_name, uma_file_type); rappor::RapporService* rappor_service = g_browser_process->rappor_service(); if (rappor_service && requestor.is_valid()) { rappor_service->RecordSample( metric_name, rappor::SAFEBROWSING_RAPPOR_TYPE, rappor::GetDomainAndRegistrySampleFromGURL(requestor)); } } void RecordPolicyMetric(const std::string& metric_name, int uma_file_type, const GURL& requestor) { BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(&RecordPolicyMetricOnUIThread, metric_name, uma_file_type, requestor)); } void RespondWithPolicy( const base::FilePath& file, const UnverifiedDownloadCheckCompletionCallback& callback, const GURL& requestor, UnverifiedDownloadPolicy policy) { int uma_file_type = download_protection_util::GetSBClientDownloadExtensionValueForUMA(file); if (policy == UnverifiedDownloadPolicy::ALLOWED) { RecordPolicyMetric("SafeBrowsing.UnverifiedDownloads.Allowed", uma_file_type, requestor); } else { RecordPolicyMetric("SafeBrowsing.UnverifiedDownloads.Blocked", uma_file_type, requestor); } BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(callback, policy)); } void CheckFieldTrialOnAnyThread( const base::FilePath& file, const GURL& requestor, const UnverifiedDownloadCheckCompletionCallback& callback) { bool is_allowed = IsUnverifiedDownloadAllowedByFieldTrial(file); RespondWithPolicy(file, callback, requestor, is_allowed ? UnverifiedDownloadPolicy::ALLOWED : UnverifiedDownloadPolicy::DISALLOWED); } void CheckWhitelistOnIOThread( scoped_refptr service, const GURL& requestor, const base::FilePath& file, const UnverifiedDownloadCheckCompletionCallback& callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); int uma_file_type = download_protection_util::GetSBClientDownloadExtensionValueForUMA(file); if (!service || !service->enabled()) { // If the SafeBrowsing service was disabled, don't try to check against the // field trial list. Instead allow the download. We are assuming that if the // SafeBrowsing service was disabled for this user, then we shouldn't // interefere with unverified downloads. RecordPolicyMetric( "SafeBrowsing.UnverifiedDownloads.AllowedDueToDisabledService", uma_file_type, requestor); RespondWithPolicy(file, callback, requestor, UnverifiedDownloadPolicy::ALLOWED); return; } if (service->database_manager() && service->database_manager()->MatchDownloadWhitelistUrl(requestor)) { RecordPolicyMetric("SafeBrowsing.UnverifiedDownloads.AllowedByWhitelist", uma_file_type, requestor); RespondWithPolicy(file, callback, requestor, UnverifiedDownloadPolicy::ALLOWED); return; } CheckFieldTrialOnAnyThread(file, requestor, callback); } } // namespace void CheckUnverifiedDownloadPolicy( const GURL& requestor, const base::FilePath& file, const UnverifiedDownloadCheckCompletionCallback& callback) { if (requestor.is_valid()) { scoped_refptr service = g_browser_process->safe_browsing_service(); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind(&CheckWhitelistOnIOThread, service, requestor, file, callback)); return; } CheckFieldTrialOnAnyThread(file, GURL(), callback); } } // namespace safe_browsing