diff options
Diffstat (limited to 'chromium/components/safe_browsing_db')
25 files changed, 313 insertions, 1158 deletions
diff --git a/chromium/components/safe_browsing_db/BUILD.gn b/chromium/components/safe_browsing_db/BUILD.gn index 68a841c69e0..fb9286f8e4c 100644 --- a/chromium/components/safe_browsing_db/BUILD.gn +++ b/chromium/components/safe_browsing_db/BUILD.gn @@ -31,9 +31,9 @@ group("safe_browsing_db_shared") { ":database_manager", ":hit_report", ":prefix_set", - ":safe_browsing_prefs", ":safebrowsing_proto", ":util", + "//components/safe_browsing/common:safe_browsing_prefs", ] } @@ -82,8 +82,8 @@ static_library("hit_report") { ":util", ] deps = [ - ":safe_browsing_prefs", "//components/metrics", + "//components/safe_browsing/common:safe_browsing_prefs", "//url", ] } @@ -152,17 +152,6 @@ static_library("safe_browsing_api_handler_util") { ] } -static_library("safe_browsing_prefs") { - sources = [ - "safe_browsing_prefs.cc", - "safe_browsing_prefs.h", - ] - deps = [ - "//base:base", - "//components/prefs", - ] -} - static_library("test_database_manager") { sources = [ "test_database_manager.cc", @@ -181,8 +170,8 @@ static_library("util") { "util.h", ] public_deps = [ - ":safe_browsing_prefs", ":v4_protocol_manager_util", + "//components/safe_browsing/common:safe_browsing_prefs", ] deps = [ "//base", @@ -325,12 +314,12 @@ static_library("v4_update_protocol_manager") { "v4_update_protocol_manager.h", ] deps = [ - ":safe_browsing_prefs", ":safebrowsing_proto", ":util", ":v4_protocol_manager_util", "//base", "//components/data_use_measurement/core", + "//components/safe_browsing/common:safe_browsing_prefs", "//net", "//url", ] @@ -413,7 +402,6 @@ source_set("unit_tests") { sources = [ "database_manager_unittest.cc", "prefix_set_unittest.cc", - "safe_browsing_prefs_unittest.cc", "util_unittest.cc", "v4_database_unittest.cc", "v4_get_hash_protocol_manager_unittest.cc", @@ -426,7 +414,6 @@ source_set("unit_tests") { deps = [ ":database_manager", ":prefix_set", - ":safe_browsing_prefs", ":safebrowsing_proto", ":test_database_manager", ":util", @@ -441,6 +428,7 @@ source_set("unit_tests") { ":v4_update_protocol_manager", "//base", "//components/prefs:test_support", + "//components/safe_browsing/common:safe_browsing_prefs", "//content/test:test_support", "//crypto", "//net", diff --git a/chromium/components/safe_browsing_db/DEPS b/chromium/components/safe_browsing_db/DEPS index 7fafc802db3..55dc17a90ee 100644 --- a/chromium/components/safe_browsing_db/DEPS +++ b/chromium/components/safe_browsing_db/DEPS @@ -1,6 +1,6 @@ include_rules = [ "+components/data_use_measurement/core", - "+components/prefs", + "+components/safe_browsing/common/safe_browsing_prefs.h", "+components/variations", "+components/version_info", "+content/public/browser", diff --git a/chromium/components/safe_browsing_db/android/safe_browsing_api_handler_bridge.cc b/chromium/components/safe_browsing_db/android/safe_browsing_api_handler_bridge.cc index a4dd994d16c..8040c2caa50 100644 --- a/chromium/components/safe_browsing_db/android/safe_browsing_api_handler_bridge.cc +++ b/chromium/components/safe_browsing_db/android/safe_browsing_api_handler_bridge.cc @@ -7,7 +7,6 @@ #include <memory> #include <string> -#include "base/android/context_utils.h" #include "base/android/jni_android.h" #include "base/android/jni_array.h" #include "base/android/jni_string.h" @@ -19,7 +18,6 @@ using base::android::AttachCurrentThread; using base::android::ConvertJavaStringToUTF8; using base::android::ConvertUTF8ToJavaString; -using base::android::GetApplicationContext; using base::android::JavaParamRef; using base::android::ScopedJavaLocalRef; using base::android::ToJavaIntArray; @@ -48,6 +46,8 @@ int SBThreatTypeToJavaThreatType(const SBThreatType& sb_threat_type) { return safe_browsing::JAVA_THREAT_TYPE_SOCIAL_ENGINEERING; case SB_THREAT_TYPE_URL_MALWARE: return safe_browsing::JAVA_THREAT_TYPE_POTENTIALLY_HARMFUL_APPLICATION; + case SB_THREAT_TYPE_URL_UNWANTED: + return safe_browsing::JAVA_THREAT_TYPE_UNWANTED_SOFTWARE; default: NOTREACHED(); return 0; @@ -121,7 +121,7 @@ void OnUrlCheckDone(JNIEnv* env, ReportUmaResult( ParseJsonFromGMSCore(metadata_str, &worst_threat, &threat_metadata)); if (worst_threat != SB_THREAT_TYPE_SAFE) { - DVLOG(1) << "Check " << callback_id << " marked as UNSAFE"; + DVLOG(1) << "Check " << callback_id << " was a MATCH"; } RunCallbackOnIOThread(*callback, worst_threat, threat_metadata); @@ -140,8 +140,7 @@ bool SafeBrowsingApiHandlerBridge::CheckApiIsSupported() { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!checked_api_support_) { DVLOG(1) << "Checking API support."; - j_api_handler_ = Java_SafeBrowsingApiBridge_create(AttachCurrentThread(), - GetApplicationContext()); + j_api_handler_ = Java_SafeBrowsingApiBridge_create(AttachCurrentThread()); checked_api_support_ = true; } return j_api_handler_.obj() != nullptr; @@ -169,10 +168,7 @@ void SafeBrowsingApiHandlerBridge::StartURLCheck( // Default threat types, to support upstream code that doesn't yet set them. std::vector<SBThreatType> local_threat_types(threat_types); - if (local_threat_types.empty()) { - local_threat_types.push_back(SB_THREAT_TYPE_URL_PHISHING); - local_threat_types.push_back(SB_THREAT_TYPE_URL_MALWARE); - } + DCHECK(!local_threat_types.empty()); JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec()); diff --git a/chromium/components/safe_browsing_db/hit_report.h b/chromium/components/safe_browsing_db/hit_report.h index afa567637f1..4fecc44c9fa 100644 --- a/chromium/components/safe_browsing_db/hit_report.h +++ b/chromium/components/safe_browsing_db/hit_report.h @@ -7,7 +7,7 @@ #ifndef COMPONENTS_SAFE_BROWSING_DB_HIT_REPORT_H_ #define COMPONENTS_SAFE_BROWSING_DB_HIT_REPORT_H_ -#include "components/safe_browsing_db/safe_browsing_prefs.h" +#include "components/safe_browsing/common/safe_browsing_prefs.h" #include "components/safe_browsing_db/util.h" #include "url/gurl.h" diff --git a/chromium/components/safe_browsing_db/remote_database_manager.cc b/chromium/components/safe_browsing_db/remote_database_manager.cc index 2def386d5f8..b620426b711 100644 --- a/chromium/components/safe_browsing_db/remote_database_manager.cc +++ b/chromium/components/safe_browsing_db/remote_database_manager.cc @@ -22,15 +22,21 @@ namespace net { class URLRequestContextGetter; } // namespace net +namespace safe_browsing { + namespace { // Android field trial for controlling types_to_check. const char kAndroidFieldExperiment[] = "SafeBrowsingAndroid"; const char kAndroidTypesToCheckParam[] = "types_to_check"; +void LogPendingChecks(size_t current_requests_size) { + UMA_HISTOGRAM_COUNTS_10000("SB2.RemoteCall.ChecksPending", + current_requests_size); +} + } // namespace -namespace safe_browsing { // // RemoteSafeBrowsingDatabaseManager::ClientRequest methods @@ -99,6 +105,10 @@ void RemoteSafeBrowsingDatabaseManager::ClientRequest::OnRequestDone( // TODO(nparker): Add more tests for this class RemoteSafeBrowsingDatabaseManager::RemoteSafeBrowsingDatabaseManager() { + // Avoid memory allocations growing the underlying vector. Although this + // usually wastes a bit of memory, it will still be less than the default + // vector allocation strategy. + resource_types_to_check_.reserve(content::RESOURCE_TYPE_LAST_TYPE + 1); // Decide which resource types to check. These two are the minimum. resource_types_to_check_.insert(content::RESOURCE_TYPE_MAIN_FRAME); resource_types_to_check_.insert(content::RESOURCE_TYPE_SUB_FRAME); @@ -183,19 +193,19 @@ bool RemoteSafeBrowsingDatabaseManager::CheckBrowseUrl(const GURL& url, return true; // Safe, continue right away. std::unique_ptr<ClientRequest> req(new ClientRequest(client, this, url)); - std::vector<SBThreatType> threat_types; // Not currently used. DVLOG(1) << "Checking for client " << client << " and URL " << url; SafeBrowsingApiHandler* api_handler = SafeBrowsingApiHandler::GetInstance(); - // This shouldn't happen since SafeBrowsingResourceThrottle checks - // IsSupported() earlier. + // This shouldn't happen since SafeBrowsingResourceThrottle and + // SubresourceFilterSafeBrowsingActivationThrottle check IsSupported() + // earlier. DCHECK(api_handler) << "SafeBrowsingApiHandler was never constructed"; api_handler->StartURLCheck( base::Bind(&ClientRequest::OnRequestDoneWeak, req->GetWeakPtr()), url, - threat_types); + {SB_THREAT_TYPE_URL_MALWARE, SB_THREAT_TYPE_URL_PHISHING, + SB_THREAT_TYPE_URL_UNWANTED}); - UMA_HISTOGRAM_COUNTS_10000("SB2.RemoteCall.ChecksPending", - current_requests_.size()); + LogPendingChecks(current_requests_.size()); current_requests_.push_back(req.release()); // Defer the resource load. @@ -225,7 +235,26 @@ bool RemoteSafeBrowsingDatabaseManager::CheckResourceUrl(const GURL& url, bool RemoteSafeBrowsingDatabaseManager::CheckUrlForSubresourceFilter( const GURL& url, Client* client) { - NOTREACHED(); + DCHECK_CURRENTLY_ON(BrowserThread::IO); + if (!enabled_ || !CanCheckUrl(url)) + return true; + + std::unique_ptr<ClientRequest> req(new ClientRequest(client, this, url)); + + DVLOG(1) << "Checking for client " << client << " and URL " << url; + SafeBrowsingApiHandler* api_handler = SafeBrowsingApiHandler::GetInstance(); + // This shouldn't happen since SafeBrowsingResourceThrottle and + // SubresourceFilterSafeBrowsingActivationThrottle check IsSupported() + // earlier. + DCHECK(api_handler) << "SafeBrowsingApiHandler was never constructed"; + api_handler->StartURLCheck( + base::Bind(&ClientRequest::OnRequestDoneWeak, req->GetWeakPtr()), url, + {SB_THREAT_TYPE_SUBRESOURCE_FILTER}); + + LogPendingChecks(current_requests_.size()); + current_requests_.push_back(req.release()); + + // Defer the resource load. return false; } diff --git a/chromium/components/safe_browsing_db/remote_database_manager.h b/chromium/components/safe_browsing_db/remote_database_manager.h index 7f8ff4ea8c8..1f13ca391fb 100644 --- a/chromium/components/safe_browsing_db/remote_database_manager.h +++ b/chromium/components/safe_browsing_db/remote_database_manager.h @@ -12,6 +12,7 @@ #include <string> #include <vector> +#include "base/containers/flat_set.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" @@ -74,7 +75,7 @@ class RemoteSafeBrowsingDatabaseManager : public SafeBrowsingDatabaseManager { // Requests currently outstanding. This owns the ptrs. std::vector<ClientRequest*> current_requests_; - std::set<content::ResourceType> resource_types_to_check_; + base::flat_set<content::ResourceType> resource_types_to_check_; friend class base::RefCountedThreadSafe<RemoteSafeBrowsingDatabaseManager>; DISALLOW_COPY_AND_ASSIGN(RemoteSafeBrowsingDatabaseManager); diff --git a/chromium/components/safe_browsing_db/safe_browsing_api_handler_unittest.cc b/chromium/components/safe_browsing_db/safe_browsing_api_handler_unittest.cc index fbf07be6136..c466dd99021 100644 --- a/chromium/components/safe_browsing_db/safe_browsing_api_handler_unittest.cc +++ b/chromium/components/safe_browsing_db/safe_browsing_api_handler_unittest.cc @@ -59,12 +59,12 @@ TEST_F(SafeBrowsingApiHandlerUtilTest, BadJson) { } TEST_F(SafeBrowsingApiHandlerUtilTest, BasicThreats) { - EXPECT_EQ(UMA_STATUS_UNSAFE, + EXPECT_EQ(UMA_STATUS_MATCH, ResetAndParseJson("{\"matches\":[{\"threat_type\":\"4\"}]}")); EXPECT_EQ(SB_THREAT_TYPE_URL_MALWARE, threat_); EXPECT_EQ(empty_meta_, meta_); - EXPECT_EQ(UMA_STATUS_UNSAFE, + EXPECT_EQ(UMA_STATUS_MATCH, ResetAndParseJson("{\"matches\":[{\"threat_type\":\"5\"}]}")); EXPECT_EQ(SB_THREAT_TYPE_URL_PHISHING, threat_); EXPECT_EQ(empty_meta_, meta_); @@ -72,7 +72,7 @@ TEST_F(SafeBrowsingApiHandlerUtilTest, BasicThreats) { TEST_F(SafeBrowsingApiHandlerUtilTest, MultipleThreats) { EXPECT_EQ( - UMA_STATUS_UNSAFE, + UMA_STATUS_MATCH, ResetAndParseJson( "{\"matches\":[{\"threat_type\":\"4\"}, {\"threat_type\":\"5\"}]}")); EXPECT_EQ(SB_THREAT_TYPE_URL_MALWARE, threat_); @@ -82,7 +82,7 @@ TEST_F(SafeBrowsingApiHandlerUtilTest, MultipleThreats) { TEST_F(SafeBrowsingApiHandlerUtilTest, PhaSubType) { ThreatMetadata expected; - EXPECT_EQ(UMA_STATUS_UNSAFE, + EXPECT_EQ(UMA_STATUS_MATCH, ResetAndParseJson("{\"matches\":[{\"threat_type\":\"4\", " "\"pha_pattern_type\":\"LANDING\"}]}")); EXPECT_EQ(SB_THREAT_TYPE_URL_MALWARE, threat_); @@ -91,14 +91,14 @@ TEST_F(SafeBrowsingApiHandlerUtilTest, PhaSubType) { // Test the ThreatMetadata comparitor for this field. EXPECT_NE(empty_meta_, meta_); - EXPECT_EQ(UMA_STATUS_UNSAFE, + EXPECT_EQ(UMA_STATUS_MATCH, ResetAndParseJson("{\"matches\":[{\"threat_type\":\"4\", " "\"pha_pattern_type\":\"DISTRIBUTION\"}]}")); EXPECT_EQ(SB_THREAT_TYPE_URL_MALWARE, threat_); expected.threat_pattern_type = ThreatPatternType::MALWARE_DISTRIBUTION; EXPECT_EQ(expected, meta_); - EXPECT_EQ(UMA_STATUS_UNSAFE, + EXPECT_EQ(UMA_STATUS_MATCH, ResetAndParseJson("{\"matches\":[{\"threat_type\":\"4\", " "\"pha_pattern_type\":\"junk\"}]}")); EXPECT_EQ(empty_meta_, meta_); @@ -108,14 +108,14 @@ TEST_F(SafeBrowsingApiHandlerUtilTest, SocialEngineeringSubType) { ThreatMetadata expected; EXPECT_EQ( - UMA_STATUS_UNSAFE, + UMA_STATUS_MATCH, ResetAndParseJson("{\"matches\":[{\"threat_type\":\"5\", " "\"se_pattern_type\":\"SOCIAL_ENGINEERING_ADS\"}]}")); EXPECT_EQ(SB_THREAT_TYPE_URL_PHISHING, threat_); expected.threat_pattern_type = ThreatPatternType::SOCIAL_ENGINEERING_ADS; EXPECT_EQ(expected, meta_); - EXPECT_EQ(UMA_STATUS_UNSAFE, + EXPECT_EQ(UMA_STATUS_MATCH, ResetAndParseJson( "{\"matches\":[{\"threat_type\":\"5\", " "\"se_pattern_type\":\"SOCIAL_ENGINEERING_LANDING\"}]}")); @@ -123,14 +123,14 @@ TEST_F(SafeBrowsingApiHandlerUtilTest, SocialEngineeringSubType) { expected.threat_pattern_type = ThreatPatternType::SOCIAL_ENGINEERING_LANDING; EXPECT_EQ(expected, meta_); - EXPECT_EQ(UMA_STATUS_UNSAFE, + EXPECT_EQ(UMA_STATUS_MATCH, ResetAndParseJson("{\"matches\":[{\"threat_type\":\"5\", " "\"se_pattern_type\":\"PHISHING\"}]}")); EXPECT_EQ(SB_THREAT_TYPE_URL_PHISHING, threat_); expected.threat_pattern_type = ThreatPatternType::PHISHING; EXPECT_EQ(expected, meta_); - EXPECT_EQ(UMA_STATUS_UNSAFE, + EXPECT_EQ(UMA_STATUS_MATCH, ResetAndParseJson("{\"matches\":[{\"threat_type\":\"5\", " "\"se_pattern_type\":\"junk\"}]}")); EXPECT_EQ(empty_meta_, meta_); @@ -139,7 +139,7 @@ TEST_F(SafeBrowsingApiHandlerUtilTest, SocialEngineeringSubType) { TEST_F(SafeBrowsingApiHandlerUtilTest, PopulationId) { ThreatMetadata expected; - EXPECT_EQ(UMA_STATUS_UNSAFE, + EXPECT_EQ(UMA_STATUS_MATCH, ResetAndParseJson("{\"matches\":[{\"threat_type\":\"4\", " "\"UserPopulation\":\"foobarbazz\"}]}")); EXPECT_EQ(SB_THREAT_TYPE_URL_MALWARE, threat_); @@ -149,4 +149,31 @@ TEST_F(SafeBrowsingApiHandlerUtilTest, PopulationId) { EXPECT_NE(empty_meta_, meta_); } +TEST_F(SafeBrowsingApiHandlerUtilTest, SubresourceFilterSubTypes) { + ThreatMetadata expected; + + EXPECT_EQ(UMA_STATUS_MATCH, + ResetAndParseJson("{\"matches\":[{\"threat_type\":\"13\"}]}")); + EXPECT_EQ(SB_THREAT_TYPE_SUBRESOURCE_FILTER, threat_); + expected.threat_pattern_type = ThreatPatternType::NONE; + EXPECT_EQ(expected, meta_); +} + +TEST_F(SafeBrowsingApiHandlerUtilTest, NoUnwantedSoftwareSubTypes) { + ThreatMetadata expected; + + EXPECT_EQ(UMA_STATUS_MATCH, + ResetAndParseJson("{\"matches\":[{\"threat_type\":\"3\"}]}")); + EXPECT_EQ(SB_THREAT_TYPE_URL_UNWANTED, threat_); + expected.threat_pattern_type = ThreatPatternType::NONE; + EXPECT_EQ(expected, meta_); + + EXPECT_EQ(UMA_STATUS_MATCH, + ResetAndParseJson("{\"matches\":[{\"threat_type\":\"3\", " + "\"se_pattern_type\":\"junk\"}]}")); + EXPECT_EQ(SB_THREAT_TYPE_URL_UNWANTED, threat_); + expected.threat_pattern_type = ThreatPatternType::NONE; + EXPECT_EQ(expected, meta_); +} + } // namespace safe_browsing diff --git a/chromium/components/safe_browsing_db/safe_browsing_api_handler_util.cc b/chromium/components/safe_browsing_db/safe_browsing_api_handler_util.cc index 4e894f03ee5..04b8070cd9d 100644 --- a/chromium/components/safe_browsing_db/safe_browsing_api_handler_util.cc +++ b/chromium/components/safe_browsing_db/safe_browsing_api_handler_util.cc @@ -53,6 +53,11 @@ void ReportUmaThreatSubType(SBThreatType threat_type, ThreatPatternType ParseThreatSubType( const base::DictionaryValue* match, SBThreatType threat_type) { + if (threat_type == SB_THREAT_TYPE_SUBRESOURCE_FILTER || + threat_type == SB_THREAT_TYPE_URL_UNWANTED) { + return ThreatPatternType::NONE; + } + std::string pattern_key; if (threat_type == SB_THREAT_TYPE_URL_MALWARE) { pattern_key = "pha_pattern_type"; @@ -111,25 +116,35 @@ std::string ParseUserPopulation(const base::DictionaryValue* match) { return population_id; } -int GetThreatSeverity(int java_threat_num) { - // Assign higher numbers to more severe threats. - switch (java_threat_num) { +// Returns the severity level for a given SafeBrowsing list. The lowest value is +// 0, which represents the most severe list. +int GetThreatSeverity(JavaThreatTypes threat_type) { + switch (threat_type) { case JAVA_THREAT_TYPE_POTENTIALLY_HARMFUL_APPLICATION: - return 2; + return 0; case JAVA_THREAT_TYPE_SOCIAL_ENGINEERING: return 1; - default: - // Unknown threat type - return -1; + case JAVA_THREAT_TYPE_UNWANTED_SOFTWARE: + return 2; + case JAVA_THREAT_TYPE_SUBRESOURCE_FILTER: + return 3; + case JAVA_THREAT_TYPE_MAX_VALUE: + return std::numeric_limits<int>::max(); } + NOTREACHED() << "Unhandled threat_type: " << threat_type; + return std::numeric_limits<int>::max(); } SBThreatType JavaToSBThreatType(int java_threat_num) { switch (java_threat_num) { case JAVA_THREAT_TYPE_POTENTIALLY_HARMFUL_APPLICATION: return SB_THREAT_TYPE_URL_MALWARE; + case JAVA_THREAT_TYPE_UNWANTED_SOFTWARE: + return SB_THREAT_TYPE_URL_UNWANTED; case JAVA_THREAT_TYPE_SOCIAL_ENGINEERING: return SB_THREAT_TYPE_URL_PHISHING; + case JAVA_THREAT_TYPE_SUBRESOURCE_FILTER: + return SB_THREAT_TYPE_SUBRESOURCE_FILTER; default: // Unknown threat type return SB_THREAT_TYPE_SAFE; @@ -146,9 +161,9 @@ SBThreatType JavaToSBThreatType(int java_threat_num) { // or // {"matches":[{"threat_type":"4", "UserPopulation":"YXNvZWZpbmFqO..."}] UmaRemoteCallResult ParseJsonFromGMSCore(const std::string& metadata_str, - SBThreatType* worst_threat, + SBThreatType* worst_sb_threat_type, ThreatMetadata* metadata) { - *worst_threat = SB_THREAT_TYPE_SAFE; // Default to safe. + *worst_sb_threat_type = SB_THREAT_TYPE_SAFE; // Default to safe. *metadata = ThreatMetadata(); // Default values. if (metadata_str.empty()) @@ -165,36 +180,40 @@ UmaRemoteCallResult ParseJsonFromGMSCore(const std::string& metadata_str, } // Go through each matched threat type and pick the most severe. - int worst_threat_num = -1; + JavaThreatTypes worst_threat_type = JAVA_THREAT_TYPE_MAX_VALUE; const base::DictionaryValue* worst_match = nullptr; for (size_t i = 0; i < matches->GetSize(); i++) { // Get the threat number const base::DictionaryValue* match; std::string threat_num_str; - int java_threat_num = -1; + + int threat_type_num; if (!matches->GetDictionary(i, &match) || !match->GetString(kJsonKeyThreatType, &threat_num_str) || - !base::StringToInt(threat_num_str, &java_threat_num)) { + !base::StringToInt(threat_num_str, &threat_type_num)) { continue; // Skip malformed list entries } - if (GetThreatSeverity(java_threat_num) > - GetThreatSeverity(worst_threat_num)) { - worst_threat_num = java_threat_num; + JavaThreatTypes threat_type = static_cast<JavaThreatTypes>(threat_type_num); + if (threat_type > JAVA_THREAT_TYPE_MAX_VALUE) { + threat_type = JAVA_THREAT_TYPE_MAX_VALUE; + } + if (GetThreatSeverity(threat_type) < GetThreatSeverity(worst_threat_type)) { + worst_threat_type = threat_type; worst_match = match; } } - *worst_threat = JavaToSBThreatType(worst_threat_num); - if (*worst_threat == SB_THREAT_TYPE_SAFE || !worst_match) + *worst_sb_threat_type = JavaToSBThreatType(worst_threat_type); + if (*worst_sb_threat_type == SB_THREAT_TYPE_SAFE || !worst_match) return UMA_STATUS_JSON_UNKNOWN_THREAT; // Fill in the metadata metadata->threat_pattern_type = - ParseThreatSubType(worst_match, *worst_threat); + ParseThreatSubType(worst_match, *worst_sb_threat_type); metadata->population_id = ParseUserPopulation(worst_match); - return UMA_STATUS_UNSAFE; // success + return UMA_STATUS_MATCH; // success } } // namespace safe_browsing diff --git a/chromium/components/safe_browsing_db/safe_browsing_api_handler_util.h b/chromium/components/safe_browsing_db/safe_browsing_api_handler_util.h index 0cb5e579212..f3724808f6c 100644 --- a/chromium/components/safe_browsing_db/safe_browsing_api_handler_util.h +++ b/chromium/components/safe_browsing_db/safe_browsing_api_handler_util.h @@ -21,10 +21,13 @@ enum RemoteCallResultStatus { }; // Threat types as per the Java code. -// This must match those in GMS's SafeBrowsingThreatTypes.java. +// This must match those in GMS's SafeBrowsingThreat.java. enum JavaThreatTypes { + JAVA_THREAT_TYPE_UNWANTED_SOFTWARE = 3, JAVA_THREAT_TYPE_POTENTIALLY_HARMFUL_APPLICATION = 4, JAVA_THREAT_TYPE_SOCIAL_ENGINEERING = 5, + JAVA_THREAT_TYPE_SUBRESOURCE_FILTER = 13, + JAVA_THREAT_TYPE_MAX_VALUE }; // Do not reorder or delete entries, and make sure changes here are reflected @@ -33,7 +36,7 @@ enum UmaRemoteCallResult { UMA_STATUS_INTERNAL_ERROR = 0, UMA_STATUS_TIMEOUT = 1, UMA_STATUS_SAFE = 2, - UMA_STATUS_UNSAFE = 3, + UMA_STATUS_MATCH = 3, UMA_STATUS_JSON_EMPTY = 4, UMA_STATUS_JSON_FAILED_TO_PARSE = 5, UMA_STATUS_JSON_UNKNOWN_THREAT = 6, diff --git a/chromium/components/safe_browsing_db/safe_browsing_prefs.cc b/chromium/components/safe_browsing_db/safe_browsing_prefs.cc deleted file mode 100644 index 3895131cbbe..00000000000 --- a/chromium/components/safe_browsing_db/safe_browsing_prefs.cc +++ /dev/null @@ -1,440 +0,0 @@ -// Copyright (c) 2016 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 "base/command_line.h" -#include "base/logging.h" -#include "base/metrics/histogram_macros.h" -#include "components/prefs/pref_service.h" -#include "components/safe_browsing_db/safe_browsing_prefs.h" - -namespace { - -// Switch value which force the ScoutGroupSelected pref to true. -const char kForceScoutGroupValueTrue[] = "true"; -// Switch value which force the ScoutGroupSelected pref to false. -const char kForceScoutGroupValueFalse[] = "false"; - -// Name of the Scout Transition UMA metric. -const char kScoutTransitionMetricName[] = "SafeBrowsing.Pref.Scout.Transition"; - -// Reasons that a state transition for Scout was performed. -// These values are written to logs. New enum values can be added, but -// existing enums must never be renumbered or deleted and reused. -enum ScoutTransitionReason { - // Flag forced Scout Group to true - FORCE_SCOUT_FLAG_TRUE = 0, - // Flag forced Scout Group to false - FORCE_SCOUT_FLAG_FALSE = 1, - // User in OnlyShowScout group, enters Scout Group - ONLY_SHOW_SCOUT_OPT_IN = 2, - // User in CanShowScout group, enters Scout Group immediately - CAN_SHOW_SCOUT_OPT_IN_SCOUT_GROUP_ON = 3, - // User in CanShowScout group, waiting for interstitial to enter Scout Group - CAN_SHOW_SCOUT_OPT_IN_WAIT_FOR_INTERSTITIAL = 4, - // User in CanShowScout group saw the first interstitial and entered the Scout - // Group - CAN_SHOW_SCOUT_OPT_IN_SAW_FIRST_INTERSTITIAL = 5, - // User in Control group - CONTROL = 6, - // Rollback: SBER2 on on implies SBER1 can turn on - ROLLBACK_SBER2_IMPLIES_SBER1 = 7, - // Rollback: SBER2 off so SBER1 must be turned off - ROLLBACK_NO_SBER2_SET_SBER1_FALSE = 8, - // Rollback: SBER2 absent so SBER1 must be cleared - ROLLBACK_NO_SBER2_CLEAR_SBER1 = 9, - // New reasons must be added BEFORE MAX_REASONS - MAX_REASONS -}; - -// The Extended Reporting pref that is currently active, used for UMA metrics. -// These values are written to logs. New enum values can be added, but -// existing enums must never be renumbered or deleted and reused. -enum ActiveExtendedReportingPref { - SBER1_PREF = 0, - SBER2_PREF = 1, - // New prefs must be added before MAX_SBER_PREF - MAX_SBER_PREF -}; - -// A histogram for tracking a nullable boolean, which can be false, true or -// null. These values are written to logs. New enum values can be added, but -// existing enums must never be renumbered or deleted and reused. -enum NullableBoolean { - NULLABLE_BOOLEAN_FALSE = 0, - NULLABLE_BOOLEAN_TRUE = 1, - NULLABLE_BOOLEAN_NULL = 2, - MAX_NULLABLE_BOOLEAN -}; - -NullableBoolean GetPrefValueOrNull(const PrefService& prefs, - const std::string& pref_name) { - if (!prefs.HasPrefPath(pref_name)) { - return NULLABLE_BOOLEAN_NULL; - } - return prefs.GetBoolean(pref_name) ? NULLABLE_BOOLEAN_TRUE - : NULLABLE_BOOLEAN_FALSE; -} - -// Update the correct UMA metric based on which pref was changed and which UI -// the change was made on. -void RecordExtendedReportingPrefChanged( - const PrefService& prefs, - safe_browsing::ExtendedReportingOptInLocation location) { - bool pref_value = safe_browsing::IsExtendedReportingEnabled(prefs); - - if (safe_browsing::IsScout(prefs)) { - switch (location) { - case safe_browsing::SBER_OPTIN_SITE_CHROME_SETTINGS: - UMA_HISTOGRAM_BOOLEAN( - "SafeBrowsing.Pref.Scout.SetPref.SBER2Pref.ChromeSettings", - pref_value); - break; - case safe_browsing::SBER_OPTIN_SITE_ANDROID_SETTINGS: - UMA_HISTOGRAM_BOOLEAN( - "SafeBrowsing.Pref.Scout.SetPref.SBER2Pref.AndroidSettings", - pref_value); - break; - case safe_browsing::SBER_OPTIN_SITE_DOWNLOAD_FEEDBACK_POPUP: - UMA_HISTOGRAM_BOOLEAN( - "SafeBrowsing.Pref.Scout.SetPref.SBER2Pref.DownloadPopup", - pref_value); - break; - case safe_browsing::SBER_OPTIN_SITE_SECURITY_INTERSTITIAL: - UMA_HISTOGRAM_BOOLEAN( - "SafeBrowsing.Pref.Scout.SetPref.SBER2Pref.SecurityInterstitial", - pref_value); - break; - default: - NOTREACHED(); - } - } else { - switch (location) { - case safe_browsing::SBER_OPTIN_SITE_CHROME_SETTINGS: - UMA_HISTOGRAM_BOOLEAN( - "SafeBrowsing.Pref.Scout.SetPref.SBER1Pref.ChromeSettings", - pref_value); - break; - case safe_browsing::SBER_OPTIN_SITE_ANDROID_SETTINGS: - UMA_HISTOGRAM_BOOLEAN( - "SafeBrowsing.Pref.Scout.SetPref.SBER1Pref.AndroidSettings", - pref_value); - break; - case safe_browsing::SBER_OPTIN_SITE_DOWNLOAD_FEEDBACK_POPUP: - UMA_HISTOGRAM_BOOLEAN( - "SafeBrowsing.Pref.Scout.SetPref.SBER1Pref.DownloadPopup", - pref_value); - break; - case safe_browsing::SBER_OPTIN_SITE_SECURITY_INTERSTITIAL: - UMA_HISTOGRAM_BOOLEAN( - "SafeBrowsing.Pref.Scout.SetPref.SBER1Pref.SecurityInterstitial", - pref_value); - break; - default: - NOTREACHED(); - } - } -} -} // namespace - -namespace prefs { -const char kSafeBrowsingExtendedReportingEnabled[] = - "safebrowsing.extended_reporting_enabled"; -const char kSafeBrowsingScoutReportingEnabled[] = - "safebrowsing.scout_reporting_enabled"; -const char kSafeBrowsingScoutGroupSelected[] = - "safebrowsing.scout_group_selected"; -const char kSafeBrowsingSawInterstitialExtendedReporting[] = - "safebrowsing.saw_interstitial_sber1"; -const char kSafeBrowsingSawInterstitialScoutReporting[] = - "safebrowsing.saw_interstitial_sber2"; -} // namespace prefs - -namespace safe_browsing { - -const char kSwitchForceScoutGroup[] = "force-scout-group"; - -const base::Feature kCanShowScoutOptIn{"CanShowScoutOptIn", - base::FEATURE_DISABLED_BY_DEFAULT}; - -const base::Feature kOnlyShowScoutOptIn{"OnlyShowScoutOptIn", - base::FEATURE_DISABLED_BY_DEFAULT}; - -std::string ChooseOptInTextPreference( - const PrefService& prefs, - const std::string& extended_reporting_pref, - const std::string& scout_pref) { - return IsScout(prefs) ? scout_pref : extended_reporting_pref; -} - -int ChooseOptInTextResource(const PrefService& prefs, - int extended_reporting_resource, - int scout_resource) { - return IsScout(prefs) ? scout_resource : extended_reporting_resource; -} - -bool ExtendedReportingPrefExists(const PrefService& prefs) { - return prefs.HasPrefPath(GetExtendedReportingPrefName(prefs)); -} - -ExtendedReportingLevel GetExtendedReportingLevel(const PrefService& prefs) { - if (!IsExtendedReportingEnabled(prefs)) { - return SBER_LEVEL_OFF; - } else { - return IsScout(prefs) ? SBER_LEVEL_SCOUT : SBER_LEVEL_LEGACY; - } -} - -const char* GetExtendedReportingPrefName(const PrefService& prefs) { - // The Scout pref is active if either of the experiment features are on, and - // ScoutGroupSelected is on as well. - if ((base::FeatureList::IsEnabled(kCanShowScoutOptIn) || - base::FeatureList::IsEnabled(kOnlyShowScoutOptIn)) && - prefs.GetBoolean(prefs::kSafeBrowsingScoutGroupSelected)) { - return prefs::kSafeBrowsingScoutReportingEnabled; - } - - // ..otherwise, either no experiment is on (ie: the Control group) or - // ScoutGroupSelected is off. So we use the SBER pref instead. - return prefs::kSafeBrowsingExtendedReportingEnabled; -} - -void InitializeSafeBrowsingPrefs(PrefService* prefs) { - // First handle forcing kSafeBrowsingScoutGroupSelected pref via cmd-line. - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - kSwitchForceScoutGroup)) { - std::string switch_value = - base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - kSwitchForceScoutGroup); - if (switch_value == kForceScoutGroupValueTrue) { - prefs->SetBoolean(prefs::kSafeBrowsingScoutGroupSelected, true); - UMA_HISTOGRAM_ENUMERATION(kScoutTransitionMetricName, - FORCE_SCOUT_FLAG_TRUE, MAX_REASONS); - } else if (switch_value == kForceScoutGroupValueFalse) { - prefs->SetBoolean(prefs::kSafeBrowsingScoutGroupSelected, false); - UMA_HISTOGRAM_ENUMERATION(kScoutTransitionMetricName, - FORCE_SCOUT_FLAG_FALSE, MAX_REASONS); - } - - // If the switch is used, don't process the experiment state. - return; - } - - // Handle the three possible experiment states. - if (base::FeatureList::IsEnabled(kOnlyShowScoutOptIn)) { - // OnlyShowScoutOptIn immediately turns on ScoutGroupSelected pref. - prefs->SetBoolean(prefs::kSafeBrowsingScoutGroupSelected, true); - UMA_HISTOGRAM_ENUMERATION(kScoutTransitionMetricName, - ONLY_SHOW_SCOUT_OPT_IN, MAX_REASONS); - } else if (base::FeatureList::IsEnabled(kCanShowScoutOptIn)) { - // CanShowScoutOptIn will only turn on ScoutGroupSelected pref if the legacy - // SBER pref is false. Otherwise the legacy SBER pref will stay on and - // continue to be used until the next security incident, at which point - // the Scout pref will become the active one. - if (!prefs->GetBoolean(prefs::kSafeBrowsingExtendedReportingEnabled)) { - prefs->SetBoolean(prefs::kSafeBrowsingScoutGroupSelected, true); - UMA_HISTOGRAM_ENUMERATION(kScoutTransitionMetricName, - CAN_SHOW_SCOUT_OPT_IN_SCOUT_GROUP_ON, - MAX_REASONS); - } else { - UMA_HISTOGRAM_ENUMERATION(kScoutTransitionMetricName, - CAN_SHOW_SCOUT_OPT_IN_WAIT_FOR_INTERSTITIAL, - MAX_REASONS); - } - } else { - // Both experiment features are off, so this is the Control group. We must - // handle the possibility that the user was previously in an experiment - // group (above) that was reverted. We want to restore the user to a - // reasonable state based on the ScoutGroup and ScoutReporting preferences. - UMA_HISTOGRAM_ENUMERATION(kScoutTransitionMetricName, CONTROL, MAX_REASONS); - bool transitioned = false; - if (prefs->GetBoolean(prefs::kSafeBrowsingScoutReportingEnabled)) { - // User opted-in to Scout which is broader than legacy Extended Reporting. - // Opt them in to Extended Reporting. - prefs->SetBoolean(prefs::kSafeBrowsingExtendedReportingEnabled, true); - UMA_HISTOGRAM_ENUMERATION(kScoutTransitionMetricName, - ROLLBACK_SBER2_IMPLIES_SBER1, MAX_REASONS); - transitioned = true; - } else if (prefs->GetBoolean(prefs::kSafeBrowsingScoutGroupSelected)) { - // User was in the Scout Group (ie: seeing the Scout opt-in text) but did - // NOT opt-in to Scout. Assume this was a conscious choice and remove - // their legacy Extended Reporting opt-in as well. The user will have a - // chance to evaluate their choice next time they see the opt-in text. - - // We make the Extended Reporting pref mimic the state of the Scout - // Reporting pref. So we either Clear it or set it to False. - if (prefs->HasPrefPath(prefs::kSafeBrowsingScoutReportingEnabled)) { - // Scout Reporting pref was explicitly set to false, so set the SBER - // pref to false. - prefs->SetBoolean(prefs::kSafeBrowsingExtendedReportingEnabled, false); - UMA_HISTOGRAM_ENUMERATION(kScoutTransitionMetricName, - ROLLBACK_NO_SBER2_SET_SBER1_FALSE, - MAX_REASONS); - } else { - // Scout Reporting pref is unset, so clear the SBER pref. - prefs->ClearPref(prefs::kSafeBrowsingExtendedReportingEnabled); - UMA_HISTOGRAM_ENUMERATION(kScoutTransitionMetricName, - ROLLBACK_NO_SBER2_CLEAR_SBER1, MAX_REASONS); - } - transitioned = true; - } - - // Also clear both the Scout settings to start over from a clean state and - // avoid the above logic from triggering on next restart. - prefs->ClearPref(prefs::kSafeBrowsingScoutGroupSelected); - prefs->ClearPref(prefs::kSafeBrowsingScoutReportingEnabled); - - // Also forget that the user has seen any interstitials if they're - // reverting back to a clean state. - if (transitioned) { - prefs->ClearPref(prefs::kSafeBrowsingSawInterstitialExtendedReporting); - prefs->ClearPref(prefs::kSafeBrowsingSawInterstitialScoutReporting); - } - } -} - -bool IsExtendedReportingEnabled(const PrefService& prefs) { - return prefs.GetBoolean(GetExtendedReportingPrefName(prefs)); -} - -bool IsScout(const PrefService& prefs) { - return GetExtendedReportingPrefName(prefs) == - prefs::kSafeBrowsingScoutReportingEnabled; -} - -void RecordExtendedReportingMetrics(const PrefService& prefs) { - // This metric tracks the extended browsing opt-in based on whichever setting - // the user is currently seeing. It tells us whether extended reporting is - // happening for this user. - UMA_HISTOGRAM_BOOLEAN("SafeBrowsing.Pref.Extended", - IsExtendedReportingEnabled(prefs)); - - // Track whether this user has ever seen a security interstitial. - UMA_HISTOGRAM_BOOLEAN( - "SafeBrowsing.Pref.SawInterstitial.SBER1Pref", - prefs.GetBoolean(prefs::kSafeBrowsingSawInterstitialExtendedReporting)); - UMA_HISTOGRAM_BOOLEAN( - "SafeBrowsing.Pref.SawInterstitial.SBER2Pref", - prefs.GetBoolean(prefs::kSafeBrowsingSawInterstitialScoutReporting)); - - // These metrics track the Scout transition. - if (prefs.GetBoolean(prefs::kSafeBrowsingScoutGroupSelected)) { - // Users in the Scout group: currently seeing the Scout opt-in. - UMA_HISTOGRAM_ENUMERATION( - "SafeBrowsing.Pref.Scout.ScoutGroup.SBER1Pref", - GetPrefValueOrNull(prefs, prefs::kSafeBrowsingExtendedReportingEnabled), - MAX_NULLABLE_BOOLEAN); - UMA_HISTOGRAM_ENUMERATION( - "SafeBrowsing.Pref.Scout.ScoutGroup.SBER2Pref", - GetPrefValueOrNull(prefs, prefs::kSafeBrowsingScoutReportingEnabled), - MAX_NULLABLE_BOOLEAN); - } else { - // Users not in the Scout group: currently seeing the SBER opt-in. - UMA_HISTOGRAM_ENUMERATION( - "SafeBrowsing.Pref.Scout.NoScoutGroup.SBER1Pref", - GetPrefValueOrNull(prefs, prefs::kSafeBrowsingExtendedReportingEnabled), - MAX_NULLABLE_BOOLEAN); - // The following metric is a corner case. User was previously in the - // Scout group and was able to opt-in to the Scout pref, but was since - // removed from the Scout group (eg: by rolling back a Scout experiment). - UMA_HISTOGRAM_ENUMERATION( - "SafeBrowsing.Pref.Scout.NoScoutGroup.SBER2Pref", - GetPrefValueOrNull(prefs, prefs::kSafeBrowsingScoutReportingEnabled), - MAX_NULLABLE_BOOLEAN); - } -} - -void SetExtendedReportingPrefAndMetric( - PrefService* prefs, - bool value, - ExtendedReportingOptInLocation location) { - prefs->SetBoolean(GetExtendedReportingPrefName(*prefs), value); - RecordExtendedReportingPrefChanged(*prefs, location); -} - -void SetExtendedReportingPref(PrefService* prefs, bool value) { - prefs->SetBoolean(GetExtendedReportingPrefName(*prefs), value); -} - -void UpdateMetricsAfterSecurityInterstitial(const PrefService& prefs, - bool on_show_pref_existed, - bool on_show_pref_value) { - const ActiveExtendedReportingPref active_pref = - IsScout(prefs) ? SBER2_PREF : SBER1_PREF; - const bool cur_pref_value = IsExtendedReportingEnabled(prefs); - - if (!on_show_pref_existed) { - if (!ExtendedReportingPrefExists(prefs)) { - // User seeing pref for the first time, didn't touch the checkbox (left it - // unchecked). - UMA_HISTOGRAM_ENUMERATION( - "SafeBrowsing.Pref.Scout.Decision.First_LeftUnchecked", active_pref, - MAX_SBER_PREF); - return; - } - - // Pref currently exists so user did something to the checkbox - if (cur_pref_value) { - // User turned the pref on. - UMA_HISTOGRAM_ENUMERATION( - "SafeBrowsing.Pref.Scout.Decision.First_Enabled", active_pref, - MAX_SBER_PREF); - return; - } - - // Otherwise, user turned the pref off, but because it didn't exist when - // the interstitial was first shown, they must have turned it on and then - // off before the interstitial was closed. - UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.Pref.Scout.Decision.First_Disabled", - active_pref, MAX_SBER_PREF); - return; - } - - // At this point, the pref existed when the interstitial was shown so this is - // a repeat appearance of the opt-in. Existence can't be removed during an - // interstitial so no need to check whether the pref currently exists. - if (on_show_pref_value && cur_pref_value) { - // User left the pref on. - UMA_HISTOGRAM_ENUMERATION( - "SafeBrowsing.Pref.Scout.Decision.Repeat_LeftEnabled", active_pref, - MAX_SBER_PREF); - return; - } else if (on_show_pref_value && !cur_pref_value) { - // User turned the pref off. - UMA_HISTOGRAM_ENUMERATION( - "SafeBrowsing.Pref.Scout.Decision.Repeat_Disabled", active_pref, - MAX_SBER_PREF); - return; - } else if (!on_show_pref_value && cur_pref_value) { - // User turned the pref on. - UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.Pref.Scout.Decision.Repeat_Enabled", - active_pref, MAX_SBER_PREF); - return; - } else { - // Both on_show and cur values are false - user left the pref off. - UMA_HISTOGRAM_ENUMERATION( - "SafeBrowsing.Pref.Scout.Decision.Repeat_LeftDisabled", active_pref, - MAX_SBER_PREF); - return; - } -} - -void UpdatePrefsBeforeSecurityInterstitial(PrefService* prefs) { - // Move the user into the Scout Group if the CanShowScoutOptIn experiment is - // enabled and they're not in the group already. - if (base::FeatureList::IsEnabled(kCanShowScoutOptIn) && - !prefs->GetBoolean(prefs::kSafeBrowsingScoutGroupSelected)) { - prefs->SetBoolean(prefs::kSafeBrowsingScoutGroupSelected, true); - UMA_HISTOGRAM_ENUMERATION(kScoutTransitionMetricName, - CAN_SHOW_SCOUT_OPT_IN_SAW_FIRST_INTERSTITIAL, - MAX_REASONS); - } - - // Remember that this user saw an interstitial with the current opt-in text. - prefs->SetBoolean(IsScout(*prefs) - ? prefs::kSafeBrowsingSawInterstitialScoutReporting - : prefs::kSafeBrowsingSawInterstitialExtendedReporting, - true); -} - -} // namespace safe_browsing diff --git a/chromium/components/safe_browsing_db/safe_browsing_prefs.h b/chromium/components/safe_browsing_db/safe_browsing_prefs.h deleted file mode 100644 index 54666f3b80b..00000000000 --- a/chromium/components/safe_browsing_db/safe_browsing_prefs.h +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright (c) 2016 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. -// -// Safe Browsing preferences and some basic utility functions for using them. - -#ifndef COMPONENTS_SAFE_BROWSING_DB_SAFE_BROWSING_PREFS_H_ -#define COMPONENTS_SAFE_BROWSING_DB_SAFE_BROWSING_PREFS_H_ - -#include "base/feature_list.h" - -class PrefService; - -namespace prefs { -// Boolean that tell us whether Safe Browsing extended reporting is enabled. -extern const char kSafeBrowsingExtendedReportingEnabled[]; - -// Boolean indicating whether Safe Browsing Scout reporting is enabled, which -// collects data for malware detection. -extern const char kSafeBrowsingScoutReportingEnabled[]; - -// Boolean indicating whether the Scout reporting workflow is enabled. This -// affects which of SafeBrowsingExtendedReporting or SafeBrowsingScoutReporting -// is used. -extern const char kSafeBrowsingScoutGroupSelected[]; - -// Boolean indicating whether the user has ever seen a security interstitial -// containing the legacy Extended Reporting opt-in. -extern const char kSafeBrowsingSawInterstitialExtendedReporting[]; - -// Boolean indicating whether the user has ever seen a security interstitial -// containing the new Scout opt-in. -extern const char kSafeBrowsingSawInterstitialScoutReporting[]; -} - -namespace safe_browsing { - -// Command-line switch for changing the scout_group_selected preference. Should -// be set to either 'true' or 'false'. Primarily for testing purposes. -// TODO: this is temporary (crbug.com/662944) -extern const char kSwitchForceScoutGroup[]; - -// When this feature is enabled, the Scout opt-in text will be displayed as of -// the next security incident. Until then, the legacy SBER text will appear. -// TODO: this is temporary (crbug.com/662944) -extern const base::Feature kCanShowScoutOptIn; - -// When this feature is enabled, the Scout opt-in text will immediately be -// displayed everywhere. -// TODO: this is temporary (crbug.com/662944) -extern const base::Feature kOnlyShowScoutOptIn; - -// Enumerates the level of Safe Browsing Extended Reporting that is currently -// available. -enum ExtendedReportingLevel { - // Extended reporting is off. - SBER_LEVEL_OFF = 0, - // The Legacy level of extended reporting is available, reporting happens in - // response to security incidents. - SBER_LEVEL_LEGACY = 1, - // The Scout level of extended reporting is available, some data can be - // collected to actively detect dangerous apps and sites. - SBER_LEVEL_SCOUT = 2, -}; - -// Enumerates all the places where the Safe Browsing Extended Reporting -// preference can be changed. -// These values are written to logs. New enum values can be added, but -// existing enums must never be renumbered or deleted and reused. -enum ExtendedReportingOptInLocation { - // The chrome://settings UI (also shared with chrome://md-settings). - SBER_OPTIN_SITE_CHROME_SETTINGS = 0, - // The Android settings UI. - SBER_OPTIN_SITE_ANDROID_SETTINGS = 1, - // The Download Feedback popup. - SBER_OPTIN_SITE_DOWNLOAD_FEEDBACK_POPUP = 2, - // Any security interstitial (malware, SSL, etc). - SBER_OPTIN_SITE_SECURITY_INTERSTITIAL = 3, - // New sites must be added before SBER_OPTIN_SITE_MAX. - SBER_OPTIN_SITE_MAX -}; - -// Determines which opt-in text should be used based on the currently active -// preference. Will return either |extended_reporting_pref| if the legacy -// Extended Reporting pref is active, or |scout_pref| if the Scout pref is -// active. Used for Android. -std::string ChooseOptInTextPreference( - const PrefService& prefs, - const std::string& extended_reporting_pref, - const std::string& scout_pref); - -// Determines which opt-in text should be used based on the currently active -// preference. Will return either |extended_reporting_resource| if the legacy -// Extended Reporting pref is active, or |scout_resource| if the Scout pref is -// active. -int ChooseOptInTextResource(const PrefService& prefs, - int extended_reporting_resource, - int scout_resource); - -// Returns whether the currently active Safe Browsing Extended Reporting -// preference exists (eg: has been set before). -bool ExtendedReportingPrefExists(const PrefService& prefs); - -// Returns the level of reporting available for the current user. -ExtendedReportingLevel GetExtendedReportingLevel(const PrefService& prefs); - -// Returns the name of the Safe Browsing Extended Reporting pref that is -// currently in effect. The specific pref in-use may change through experiments. -const char* GetExtendedReportingPrefName(const PrefService& prefs); - -// Initializes Safe Browsing preferences based on data such as experiment state, -// command line flags, etc. -// TODO: this is temporary (crbug.com/662944) -void InitializeSafeBrowsingPrefs(PrefService* prefs); - -// Returns whether Safe Browsing Extended Reporting is currently enabled. -// This should be used to decide if any of the reporting preferences are set, -// regardless of which specific one is set. -bool IsExtendedReportingEnabled(const PrefService& prefs); - -// Returns whether the currently-active Extended Reporting pref is Scout. -bool IsScout(const PrefService& prefs); - -// Updates UMA metrics about Safe Browsing Extended Reporting states. -void RecordExtendedReportingMetrics(const PrefService& prefs); - -// Sets the currently active Safe Browsing Extended Reporting preference to the -// specified value. The |location| indicates the UI where the change was -// made. -void SetExtendedReportingPrefAndMetric(PrefService* prefs, - bool value, - ExtendedReportingOptInLocation location); -// This variant is used to simplify test code by omitting the location. -void SetExtendedReportingPref(PrefService* prefs, bool value); - -// Called when a security interstitial is closed by the user. -// |on_show_pref_existed| indicates whether the pref existed when the -// interstitial was shown. |on_show_pref_value| contains the pref value when the -// interstitial was shown. -void UpdateMetricsAfterSecurityInterstitial(const PrefService& prefs, - bool on_show_pref_existed, - bool on_show_pref_value); - -// Called to indicate that a security interstitial is about to be shown to the -// user. This may trigger the user to begin seeing the Scout opt-in text -// depending on their experiment state. -void UpdatePrefsBeforeSecurityInterstitial(PrefService* prefs); - -} // namespace safe_browsing - -#endif // COMPONENTS_SAFE_BROWSING_DB_SAFE_BROWSING_PREFS_H_ diff --git a/chromium/components/safe_browsing_db/safe_browsing_prefs_unittest.cc b/chromium/components/safe_browsing_db/safe_browsing_prefs_unittest.cc deleted file mode 100644 index b6b3a088b45..00000000000 --- a/chromium/components/safe_browsing_db/safe_browsing_prefs_unittest.cc +++ /dev/null @@ -1,462 +0,0 @@ -// Copyright 2016 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 <string> -#include <vector> - -#include "base/command_line.h" -#include "base/strings/string_piece.h" -#include "base/strings/string_util.h" -#include "base/test/scoped_feature_list.h" -#include "components/prefs/pref_registry_simple.h" -#include "components/prefs/testing_pref_service.h" -#include "components/safe_browsing_db/safe_browsing_prefs.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace safe_browsing { - -class SafeBrowsingPrefsTest : public ::testing::Test { - protected: - void SetUp() override { - prefs_.registry()->RegisterBooleanPref( - prefs::kSafeBrowsingExtendedReportingEnabled, false); - prefs_.registry()->RegisterBooleanPref( - prefs::kSafeBrowsingScoutReportingEnabled, false); - prefs_.registry()->RegisterBooleanPref( - prefs::kSafeBrowsingScoutGroupSelected, false); - prefs_.registry()->RegisterBooleanPref( - prefs::kSafeBrowsingSawInterstitialExtendedReporting, false); - prefs_.registry()->RegisterBooleanPref( - prefs::kSafeBrowsingSawInterstitialScoutReporting, false); - - ResetExperiments(/*can_show_scout=*/false, /*only_show_scout=*/false); - } - - void ResetPrefs(bool sber_reporting, bool scout_reporting, bool scout_group) { - prefs_.SetBoolean(prefs::kSafeBrowsingExtendedReportingEnabled, - sber_reporting); - prefs_.SetBoolean(prefs::kSafeBrowsingScoutReportingEnabled, - scout_reporting); - prefs_.SetBoolean(prefs::kSafeBrowsingScoutGroupSelected, scout_group); - } - - void ResetExperiments(bool can_show_scout, bool only_show_scout) { - std::vector<base::StringPiece> enabled_features; - std::vector<base::StringPiece> disabled_features; - - auto* target_vector = - can_show_scout ? &enabled_features : &disabled_features; - target_vector->push_back(kCanShowScoutOptIn.name); - - target_vector = only_show_scout ? &enabled_features : &disabled_features; - target_vector->push_back(kOnlyShowScoutOptIn.name); - - feature_list_.reset(new base::test::ScopedFeatureList); - feature_list_->InitFromCommandLine( - base::JoinString(enabled_features, ","), - base::JoinString(disabled_features, ",")); - } - - std::string GetActivePref() { return GetExtendedReportingPrefName(prefs_); } - - // Convenience method for explicitly setting up all combinations of prefs and - // experiments. - void TestGetPrefName(bool sber_reporting, - bool scout_reporting, - bool scout_group, - bool can_show_scout, - bool only_show_scout, - const std::string& expected_pref) { - ResetPrefs(sber_reporting, scout_reporting, scout_group); - ResetExperiments(can_show_scout, only_show_scout); - EXPECT_EQ(expected_pref, GetActivePref()) - << "sber=" << sber_reporting << " scout=" << scout_reporting - << " scout_group=" << scout_group - << " can_show_scout=" << can_show_scout - << " only_show_scout=" << only_show_scout; - } - - void InitPrefs() { InitializeSafeBrowsingPrefs(&prefs_); } - - bool IsScoutGroupSelected() { - return prefs_.GetBoolean(prefs::kSafeBrowsingScoutGroupSelected); - } - - void ExpectPrefs(bool sber_reporting, - bool scout_reporting, - bool scout_group) { - LOG(INFO) << "Pref values: sber=" << sber_reporting - << " scout=" << scout_reporting << " scout_group=" << scout_group; - EXPECT_EQ(sber_reporting, - prefs_.GetBoolean(prefs::kSafeBrowsingExtendedReportingEnabled)); - EXPECT_EQ(scout_reporting, - prefs_.GetBoolean(prefs::kSafeBrowsingScoutReportingEnabled)); - EXPECT_EQ(scout_group, - prefs_.GetBoolean(prefs::kSafeBrowsingScoutGroupSelected)); - } - - void ExpectPrefsExist(bool sber_reporting, - bool scout_reporting, - bool scout_group) { - LOG(INFO) << "Prefs exist: sber=" << sber_reporting - << " scout=" << scout_reporting << " scout_group=" << scout_group; - EXPECT_EQ(sber_reporting, - prefs_.HasPrefPath(prefs::kSafeBrowsingExtendedReportingEnabled)); - EXPECT_EQ(scout_reporting, - prefs_.HasPrefPath(prefs::kSafeBrowsingScoutReportingEnabled)); - EXPECT_EQ(scout_group, - prefs_.HasPrefPath(prefs::kSafeBrowsingScoutGroupSelected)); - } - TestingPrefServiceSimple prefs_; - - private: - std::unique_ptr<base::test::ScopedFeatureList> feature_list_; -}; - -// This test ensures that we correctly select between SBER and Scout as the -// active preference in a number of common scenarios. -TEST_F(SafeBrowsingPrefsTest, GetExtendedReportingPrefName_Common) { - const std::string& sber = prefs::kSafeBrowsingExtendedReportingEnabled; - const std::string& scout = prefs::kSafeBrowsingScoutReportingEnabled; - - // By default (all prefs and experiment features disabled), SBER pref is used. - TestGetPrefName(false, false, false, false, false, sber); - - // Changing any prefs (including ScoutGroupSelected) keeps SBER as the active - // pref because the experiment remains in the Control group. - TestGetPrefName(/*sber=*/true, false, false, false, false, sber); - TestGetPrefName(false, /*scout=*/true, false, false, false, sber); - TestGetPrefName(false, false, /*scout_group=*/true, false, false, sber); - - // Being in either experiment group with ScoutGroup selected makes Scout the - // active pref. - TestGetPrefName(false, false, /*scout_group=*/true, /*can_show_scout=*/true, - false, scout); - TestGetPrefName(false, false, /*scout_group=*/true, false, - /*only_show_scout=*/true, scout); - - // When ScoutGroup is not selected then SBER remains the active pref, - // regardless which experiment is enabled. - TestGetPrefName(false, false, false, /*can_show_scout=*/true, false, sber); - TestGetPrefName(false, false, false, false, /*only_show_scout=*/true, sber); -} - -// Here we exhaustively check all combinations of pref and experiment states. -// This should help catch regressions. -TEST_F(SafeBrowsingPrefsTest, GetExtendedReportingPrefName_Exhaustive) { - const std::string& sber = prefs::kSafeBrowsingExtendedReportingEnabled; - const std::string& scout = prefs::kSafeBrowsingScoutReportingEnabled; - TestGetPrefName(false, false, false, false, false, sber); - TestGetPrefName(false, false, false, false, true, sber); - TestGetPrefName(false, false, false, true, false, sber); - TestGetPrefName(false, false, false, true, true, sber); - TestGetPrefName(false, false, true, false, false, sber); - TestGetPrefName(false, false, true, false, true, scout); - TestGetPrefName(false, false, true, true, false, scout); - TestGetPrefName(false, false, true, true, true, scout); - TestGetPrefName(false, true, false, false, false, sber); - TestGetPrefName(false, true, false, false, true, sber); - TestGetPrefName(false, true, false, true, false, sber); - TestGetPrefName(false, true, false, true, true, sber); - TestGetPrefName(false, true, true, false, false, sber); - TestGetPrefName(false, true, true, false, true, scout); - TestGetPrefName(false, true, true, true, false, scout); - TestGetPrefName(false, true, true, true, true, scout); - TestGetPrefName(true, false, false, false, false, sber); - TestGetPrefName(true, false, false, false, true, sber); - TestGetPrefName(true, false, false, true, false, sber); - TestGetPrefName(true, false, false, true, true, sber); - TestGetPrefName(true, false, true, false, false, sber); - TestGetPrefName(true, false, true, false, true, scout); - TestGetPrefName(true, false, true, true, false, scout); - TestGetPrefName(true, false, true, true, true, scout); - TestGetPrefName(true, true, false, false, false, sber); - TestGetPrefName(true, true, false, false, true, sber); - TestGetPrefName(true, true, false, true, false, sber); - TestGetPrefName(true, true, false, true, true, sber); - TestGetPrefName(true, true, true, false, false, sber); - TestGetPrefName(true, true, true, false, true, scout); - TestGetPrefName(true, true, true, true, false, scout); - TestGetPrefName(true, true, true, true, true, scout); -} - -// Basic test that command-line flags can force the ScoutGroupSelected pref on -// or off. -TEST_F(SafeBrowsingPrefsTest, InitPrefs_ForceScoutGroupOnOff) { - // By default ScoutGroupSelected is off. - EXPECT_FALSE(IsScoutGroupSelected()); - - // Command-line flag can force it on during initialization. - base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( - kSwitchForceScoutGroup, "true"); - InitPrefs(); - EXPECT_TRUE(IsScoutGroupSelected()); - - // ScoutGroup remains on if switches are cleared, but only if an experiment - // is active (since being in the Control group automatically clears the - // Scout prefs). - base::CommandLine::StringVector empty; - base::CommandLine::ForCurrentProcess()->InitFromArgv(empty); - ResetExperiments(/*can_show_scout=*/true, /*only_show_scout=*/false); - EXPECT_TRUE(IsScoutGroupSelected()); - - // Nonsense values are ignored and ScoutGroup is unchanged. - base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( - kSwitchForceScoutGroup, "foo"); - InitPrefs(); - EXPECT_TRUE(IsScoutGroupSelected()); - - // ScoutGroup can also be forced off during initialization. - base::CommandLine::ForCurrentProcess()->InitFromArgv(empty); - base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( - kSwitchForceScoutGroup, "false"); - InitPrefs(); - EXPECT_FALSE(IsScoutGroupSelected()); -} - -// Test all combinations of prefs during initialization when neither experiment -// is on (ie: control group). In all cases the Scout prefs should be cleared, -// and the SBER pref may get switched. -TEST_F(SafeBrowsingPrefsTest, InitPrefs_Control) { - // Turn both experiments off. - ResetExperiments(/*can_show_scout=*/false, /*only_show_scout=*/false); - - // Default case (everything off) - no change on init. - ResetPrefs(false, false, false); - InitPrefs(); - ExpectPrefs(false, false, false); - // SBER pref exists because it was set to false above. - ExpectPrefsExist(true, false, false); - - // ScoutGroup on - SBER cleared since Scout opt-in was shown but Scout pref - // was not chosen. Scout prefs cleared. - ResetPrefs(false, false, true); - InitPrefs(); - ExpectPrefs(false, false, false); - ExpectPrefsExist(true, false, false); - - // ScoutReporting on without ScoutGroup - SBER turns on since user opted-in to - // broader Scout reporting, we can continue collecting the SBER subset. Scout - // prefs cleared. - ResetPrefs(false, true, false); - InitPrefs(); - ExpectPrefs(true, false, false); - ExpectPrefsExist(true, false, false); - - // ScoutReporting and ScoutGroup on - SBER turns on since user opted-in to - // broader Scout reporting, we can continue collecting the SBER subset. Scout - // prefs cleared. - ResetPrefs(false, true, true); - InitPrefs(); - ExpectPrefs(true, false, false); - ExpectPrefsExist(true, false, false); - - // SBER on - no change on init since ScoutGroup is off implying that user - // never saw Scout opt-in text. Scout prefs remain cleared. - ResetPrefs(true, false, false); - InitPrefs(); - ExpectPrefs(true, false, false); - ExpectPrefsExist(true, false, false); - - // SBER and ScoutGroup on - SBER cleared. User previously opted-in to SBER - // and they saw Scout opt-in text (ie. ScoutGroup on), but chose not to opt-in - // to Scout reporting. We want them to re-evaluate their choice of SBER since - // the lack of Scout opt-in was a conscious choice. Scout cleared. - ResetPrefs(true, false, true); - InitPrefs(); - ExpectPrefs(false, false, false); - ExpectPrefsExist(true, false, false); - - // SBER and ScoutReporting on. User has opted-in to broader level of reporting - // so SBER stays on. Scout prefs cleared. - ResetPrefs(true, true, false); - InitPrefs(); - ExpectPrefs(true, false, false); - ExpectPrefsExist(true, false, false); - - // Everything on. User has opted-in to broader level of reporting so SBER - // stays on. Scout prefs cleared. - ResetPrefs(true, true, true); - InitPrefs(); - ExpectPrefs(true, false, false); - ExpectPrefs(true, false, false); -} - -// Tests a unique case where the Extended Reporting pref will be Cleared instead -// of set to False in order to mimic the state of the Scout reporting pref. -// This happens when a user is in the OnlyShowScoutOptIn experiment but never -// encounters a security issue so never sees the Scout opt-in. This user then -// returns to the Control group having never seen the Scout opt-in, so their -// Scout Reporting pref is un-set. We want to return their SBER pref to the -// unset state as well. -TEST_F(SafeBrowsingPrefsTest, InitPrefs_Control_SberPrefCleared) { - // Turn both experiments off. - ResetExperiments(/*can_show_scout=*/false, /*only_show_scout=*/false); - - // Set the user's old SBER pref to on to be explicit. - prefs_.SetBoolean(prefs::kSafeBrowsingExtendedReportingEnabled, true); - // User is in the OnlyShowScoutOptIn experiment so they go directly to the - // Scout Group. - prefs_.SetBoolean(prefs::kSafeBrowsingScoutGroupSelected, true); - // But they never see a security popup or change the setting manually so the - // Scout pref remains unset. - prefs_.ClearPref(prefs::kSafeBrowsingScoutReportingEnabled); - - InitPrefs(); - - // All pref values should be false and unset. - ExpectPrefs(false, false, false); - ExpectPrefsExist(false, false, false); -} - -// Test all combinations of prefs during initialization when the CanShowScout -// experiment is on. -TEST_F(SafeBrowsingPrefsTest, InitPrefs_CanShowScout) { - // Turn the CanShowScout experiment on. - ResetExperiments(/*can_show_scout=*/true, /*only_show_scout=*/false); - - // Default case (everything off) - ScoutGroup turns on because SBER is off. - ResetPrefs(false, false, false); - InitPrefs(); - ExpectPrefs(false, false, true); - - // ScoutGroup on - no change on init since ScoutGroup is already on. - ResetPrefs(false, false, true); - InitPrefs(); - ExpectPrefs(false, false, true); - - // ScoutReporting on without ScoutGroup - ScoutGroup turns on because SBER is - // off. - ResetPrefs(false, true, false); - InitPrefs(); - ExpectPrefs(false, true, true); - - // ScoutReporting and ScoutGroup on - no change on init since ScoutGroup is - // already on. - ResetPrefs(false, true, true); - InitPrefs(); - ExpectPrefs(false, true, true); - - // SBER on - no change on init. Will wait for first security incident before - // turning on ScoutGroup and displaying the Scout opt-in. - ResetPrefs(true, false, false); - InitPrefs(); - ExpectPrefs(true, false, false); - - // SBER and ScoutGroup on - no change on init since ScoutGroup is already on. - ResetPrefs(true, false, true); - InitPrefs(); - ExpectPrefs(true, false, true); - - // SBER and ScoutReporting on - no change on init because SBER is on. - // ScoutGroup will turn on on next security incident. - ResetPrefs(true, true, false); - InitPrefs(); - ExpectPrefs(true, true, false); - - // Everything on - no change on init since ScoutGroup is already on. - ResetPrefs(true, true, true); - InitPrefs(); - ExpectPrefs(true, true, true); -} - -// Test all combinations of prefs during initialization when the OnlyShowScout -// experiment is on. -TEST_F(SafeBrowsingPrefsTest, InitPrefs_OnlyShowScout) { - // Turn the OnlyShowScout experiment on. - ResetExperiments(/*can_show_scout=*/false, /*only_show_scout=*/true); - - // Default case (everything off) - ScoutGroup turns on. - ResetPrefs(false, false, false); - InitPrefs(); - ExpectPrefs(false, false, true); - - // ScoutGroup on - no change on init since ScoutGroup is already on. - ResetPrefs(false, false, true); - InitPrefs(); - ExpectPrefs(false, false, true); - - // ScoutReporting on without ScoutGroup - ScoutGroup turns on. - ResetPrefs(false, true, false); - InitPrefs(); - ExpectPrefs(false, true, true); - - // ScoutReporting and ScoutGroup on - no change on init since ScoutGroup is - // already on. - ResetPrefs(false, true, true); - InitPrefs(); - ExpectPrefs(false, true, true); - - // SBER on - ScoutGroup turns on immediately, not waiting for first security - // incident. - ResetPrefs(true, false, false); - InitPrefs(); - ExpectPrefs(true, false, true); - - // SBER and ScoutGroup on - no change on init since ScoutGroup is already on. - ResetPrefs(true, false, true); - InitPrefs(); - ExpectPrefs(true, false, true); - - // SBER and ScoutReporting on - ScoutGroup turns on immediately, not waiting - // for first security incident. - ResetPrefs(true, true, false); - InitPrefs(); - ExpectPrefs(true, true, true); - - // Everything on - no change on init since ScoutGroup is already on. - ResetPrefs(true, true, true); - InitPrefs(); - ExpectPrefs(true, true, true); -} - -TEST_F(SafeBrowsingPrefsTest, ChooseOptInText) { - const int kSberResource = 100; - const int kScoutResource = 500; - // By default, SBER opt-in is used - EXPECT_EQ(kSberResource, - ChooseOptInTextResource(prefs_, kSberResource, kScoutResource)); - - // Enabling Scout switches to the Scout opt-in text. - ResetExperiments(/*can_show_scout=*/false, /*only_show_scout=*/true); - ResetPrefs(/*sber=*/false, /*scout=*/false, /*scout_group=*/true); - EXPECT_EQ(kScoutResource, - ChooseOptInTextResource(prefs_, kSberResource, kScoutResource)); -} - -TEST_F(SafeBrowsingPrefsTest, GetSafeBrowsingExtendedReportingLevel) { - // By Default, SBER is off - EXPECT_EQ(SBER_LEVEL_OFF, GetExtendedReportingLevel(prefs_)); - - // Opt-in to Legacy SBER gives Legacy reporting leve. - ResetPrefs(/*sber=*/true, /*scout_reporting=*/false, /*scout_group=*/false); - EXPECT_EQ(SBER_LEVEL_LEGACY, GetExtendedReportingLevel(prefs_)); - - // The value of the Scout pref doesn't change the reporting level if the user - // is outside of the Scout Group and/or no experiment is running. - // No scout group. - ResetPrefs(/*sber=*/true, /*scout_reporting=*/true, /*scout_group=*/false); - EXPECT_EQ(SBER_LEVEL_LEGACY, GetExtendedReportingLevel(prefs_)); - // Scout group but no experiment. - ResetPrefs(/*sber=*/true, /*scout_reporting=*/true, /*scout_group=*/true); - EXPECT_EQ(SBER_LEVEL_LEGACY, GetExtendedReportingLevel(prefs_)); - - // Remaining in the Scout Group and adding an experiment will switch to the - // Scout pref to determine reporting level. - ResetExperiments(/*can_show_scout=*/false, /*only_show_scout=*/true); - // Both reporting prefs off, so reporting is off. - ResetPrefs(/*sber=*/false, /*scout_reporting=*/false, /*scout_group=*/true); - EXPECT_EQ(SBER_LEVEL_OFF, GetExtendedReportingLevel(prefs_)); - // Legacy pref on when we're using Scout - reporting remains off. - ResetPrefs(/*sber=*/true, /*scout_reporting=*/false, /*scout_group=*/true); - EXPECT_EQ(SBER_LEVEL_OFF, GetExtendedReportingLevel(prefs_)); - // Turning on Scout gives us Scout level reporting - ResetPrefs(/*sber=*/false, /*scout_reporting=*/true, /*scout_group=*/true); - EXPECT_EQ(SBER_LEVEL_SCOUT, GetExtendedReportingLevel(prefs_)); - // .. and the legacy pref doesn't affect this. - ResetPrefs(/*sber=*/true, /*scout_reporting=*/true, /*scout_group=*/true); - EXPECT_EQ(SBER_LEVEL_SCOUT, GetExtendedReportingLevel(prefs_)); -} - -} // namespace safe_browsing diff --git a/chromium/components/safe_browsing_db/util.h b/chromium/components/safe_browsing_db/util.h index ad6f4e820bd..dd03f5fe03f 100644 --- a/chromium/components/safe_browsing_db/util.h +++ b/chromium/components/safe_browsing_db/util.h @@ -16,7 +16,7 @@ #include "base/strings/string_piece.h" #include "base/time/time.h" -#include "components/safe_browsing_db/safe_browsing_prefs.h" +#include "components/safe_browsing/common/safe_browsing_prefs.h" #include "components/safe_browsing_db/v4_protocol_manager_util.h" class GURL; diff --git a/chromium/components/safe_browsing_db/v4_database.cc b/chromium/components/safe_browsing_db/v4_database.cc index c1c7b3eedcd..9164951b2fb 100644 --- a/chromium/components/safe_browsing_db/v4_database.cc +++ b/chromium/components/safe_browsing_db/v4_database.cc @@ -204,17 +204,22 @@ std::unique_ptr<StoreStateMap> V4Database::GetStoreStateMap() { return store_state_map; } -bool V4Database::AreStoresAvailable( +bool V4Database::AreAnyStoresAvailable( const StoresToCheck& stores_to_check) const { DCHECK_CURRENTLY_ON(BrowserThread::IO); for (const ListIdentifier& identifier : stores_to_check) { - const auto& store_pair = store_map_->find(identifier); - if (store_pair == store_map_->end()) { - return false; // Store not in our list - } - if (!store_pair->second->HasValidData()) { - return false; // Store never properly populated. - } + if (IsStoreAvailable(identifier)) + return true; + } + return false; +} + +bool V4Database::AreAllStoresAvailable( + const StoresToCheck& stores_to_check) const { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + for (const ListIdentifier& identifier : stores_to_check) { + if (!IsStoreAvailable(identifier)) + return false; } return true; } @@ -226,6 +231,8 @@ void V4Database::GetStoresMatchingFullHash( DCHECK_CURRENTLY_ON(BrowserThread::IO); matched_store_and_hash_prefixes->clear(); for (const ListIdentifier& identifier : stores_to_check) { + if (!IsStoreAvailable(identifier)) + continue; const auto& store_pair = store_map_->find(identifier); DCHECK(store_pair != store_map_->end()); const std::unique_ptr<V4Store>& store = store_pair->second; @@ -271,6 +278,19 @@ void V4Database::VerifyChecksumOnTaskRunner( FROM_HERE, base::Bind(db_ready_for_updates_callback, stores_to_reset)); } +bool V4Database::IsStoreAvailable(const ListIdentifier& identifier) const { + const auto& store_pair = store_map_->find(identifier); + if (store_pair == store_map_->end()) { + // Store not in our list + return false; + } + if (!store_pair->second->HasValidData()) { + // Store never properly populated + return false; + } + return true; +} + void V4Database::RecordFileSizeHistograms() { int64_t db_size = 0; for (const auto& store_map_iter : *store_map_) { diff --git a/chromium/components/safe_browsing_db/v4_database.h b/chromium/components/safe_browsing_db/v4_database.h index 0fc398dcfb9..fd8b3af8148 100644 --- a/chromium/components/safe_browsing_db/v4_database.h +++ b/chromium/components/safe_browsing_db/v4_database.h @@ -20,7 +20,7 @@ #include "components/safe_browsing_db/v4_store.h" namespace subresource_filter { -class SubresourceFilterBrowserTestImpl; +class SubresourceFilterBrowserTest; } namespace safe_browsing { @@ -131,7 +131,13 @@ class V4Database { // A store may be unavailble if either it hasn't yet gotten a proper // full-update (just after install, or corrupted/missing file), or if it's // not supported in this build (i.e. Chromium). - virtual bool AreStoresAvailable(const StoresToCheck& stores_to_check) const; + virtual bool AreAllStoresAvailable( + const StoresToCheck& stores_to_check) const; + + // Check if any of the stores are available and populated. + // Returns false if all of |stores_to_check| don't have valid data. + virtual bool AreAnyStoresAvailable( + const StoresToCheck& stores_to_check) const; // Searches for a hash prefix matching the |full_hash| in stores in the // database, filtered by |stores_to_check|, and returns the identifier of the @@ -165,7 +171,7 @@ class V4Database { const std::unique_ptr<StoreMap> store_map_; private: - friend class subresource_filter::SubresourceFilterBrowserTestImpl; + friend class subresource_filter::SubresourceFilterBrowserTest; friend class V4DatabaseFactory; friend class V4DatabaseTest; friend class V4SafeBrowsingServiceTest; @@ -209,6 +215,8 @@ class V4Database { const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner, DatabaseReadyForUpdatesCallback db_ready_for_updates_callback); + bool IsStoreAvailable(const ListIdentifier& identifier) const; + const scoped_refptr<base::SequencedTaskRunner> db_task_runner_; DatabaseUpdatedCallback db_updated_callback_; diff --git a/chromium/components/safe_browsing_db/v4_database_unittest.cc b/chromium/components/safe_browsing_db/v4_database_unittest.cc index 431204551a8..66db6fa5b95 100644 --- a/chromium/components/safe_browsing_db/v4_database_unittest.cc +++ b/chromium/components/safe_browsing_db/v4_database_unittest.cc @@ -468,13 +468,22 @@ TEST_F(V4DatabaseTest, TestStoresAvailable) { const ListIdentifier bogus_id(LINUX_PLATFORM, CHROME_EXTENSION, CSD_WHITELIST); - EXPECT_TRUE(v4_database_->AreStoresAvailable( + EXPECT_TRUE(v4_database_->AreAllStoresAvailable( StoresToCheck({linux_malware_id_, win_malware_id_}))); + EXPECT_TRUE(v4_database_->AreAnyStoresAvailable( + StoresToCheck({linux_malware_id_, win_malware_id_}))); + + EXPECT_TRUE( + v4_database_->AreAllStoresAvailable(StoresToCheck({linux_malware_id_}))); + EXPECT_TRUE( + v4_database_->AreAnyStoresAvailable(StoresToCheck({linux_malware_id_}))); - EXPECT_FALSE(v4_database_->AreStoresAvailable( + EXPECT_FALSE(v4_database_->AreAllStoresAvailable( + StoresToCheck({linux_malware_id_, bogus_id}))); + EXPECT_TRUE(v4_database_->AreAnyStoresAvailable( StoresToCheck({linux_malware_id_, bogus_id}))); - EXPECT_FALSE(v4_database_->AreStoresAvailable(StoresToCheck({bogus_id}))); + EXPECT_FALSE(v4_database_->AreAllStoresAvailable(StoresToCheck({bogus_id}))); } // Test to ensure that the callback to the database is dropped when the database diff --git a/chromium/components/safe_browsing_db/v4_get_hash_protocol_manager.cc b/chromium/components/safe_browsing_db/v4_get_hash_protocol_manager.cc index eba742b203e..77488c2c422 100644 --- a/chromium/components/safe_browsing_db/v4_get_hash_protocol_manager.cc +++ b/chromium/components/safe_browsing_db/v4_get_hash_protocol_manager.cc @@ -17,6 +17,7 @@ #include "net/base/load_flags.h" #include "net/http/http_response_headers.h" #include "net/http/http_status_code.h" +#include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_fetcher.h" #include "net/url_request/url_request_context_getter.h" @@ -301,8 +302,41 @@ void V4GetHashProtocolManager::GetFullHashes( net::HttpRequestHeaders headers; GetHashUrlAndHeaders(req_base64, &gethash_url, &headers); - std::unique_ptr<net::URLFetcher> owned_fetcher = net::URLFetcher::Create( - url_fetcher_id_++, gethash_url, net::URLFetcher::GET, this); + net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("safe_browsing_v4_get_hash", R"( + semantics { + sender: "Safe Browsing" + description: + "When Safe Browsing detects that a URL might be dangerous based on " + "its local database, it sends a partial hash of that URL to Google " + "to verify it before showing a warning to the user. This partial " + "hash does not expose the URL to Google." + trigger: + "When a resource URL matches the local hash-prefix database of " + "potential threats (malware, phishing etc), and the full-hash " + "result is not already cached, this will be sent." + data: + "The 32-bit hash prefix of any potentially bad URLs. The URLs " + "themselves are not sent." + destination: GOOGLE_OWNED_SERVICE + } + policy { + cookies_allowed: true + cookies_store: "Safe Browsing cookie store" + setting: + "Users can disable Safe Browsing by unchecking 'Protect you and " + "your device from dangerous sites' in Chromium settings under " + "Privacy. The feature is enabled by default." + chrome_policy { + SafeBrowsingEnabled { + policy_options {mode: MANDATORY} + SafeBrowsingEnabled: false + } + } + })"); + std::unique_ptr<net::URLFetcher> owned_fetcher = + net::URLFetcher::Create(url_fetcher_id_++, gethash_url, + net::URLFetcher::GET, this, traffic_annotation); net::URLFetcher* fetcher = owned_fetcher.get(); pending_hash_requests_[fetcher].reset(new FullHashCallbackInfo( cached_full_hash_infos, prefixes_to_request, std::move(owned_fetcher), diff --git a/chromium/components/safe_browsing_db/v4_get_hash_protocol_manager.h b/chromium/components/safe_browsing_db/v4_get_hash_protocol_manager.h index 8a0f855da50..7d9c2c2aff1 100644 --- a/chromium/components/safe_browsing_db/v4_get_hash_protocol_manager.h +++ b/chromium/components/safe_browsing_db/v4_get_hash_protocol_manager.h @@ -14,6 +14,7 @@ #include <memory> #include <string> +#include <unordered_map> #include <utility> #include <vector> @@ -39,7 +40,7 @@ namespace safe_browsing { // The matching hash prefixes and corresponding stores, for each full hash // generated for a given URL. -typedef base::hash_map<FullHash, StoreAndHashPrefixes> +typedef std::unordered_map<FullHash, StoreAndHashPrefixes> FullHashToStoreAndHashPrefixesMap; // ---------------------------------------------------------------- @@ -90,7 +91,7 @@ struct CachedHashPrefixInfo { // Cached full hashes received from the server for the corresponding hash // prefixes. -typedef base::hash_map<HashPrefix, CachedHashPrefixInfo> FullHashCache; +typedef std::unordered_map<HashPrefix, CachedHashPrefixInfo> FullHashCache; // FullHashCallback is invoked when GetFullHashes completes. The parameter is // the vector of full hash results. If empty, indicates that there were no @@ -295,8 +296,8 @@ class V4GetHashProtocolManager : public net::URLFetcherDelegate, private: // Map of GetHash requests to parameters which created it. using PendingHashRequests = - base::hash_map<const net::URLFetcher*, - std::unique_ptr<FullHashCallbackInfo>>; + std::unordered_map<const net::URLFetcher*, + std::unique_ptr<FullHashCallbackInfo>>; // The factory that controls the creation of V4GetHashProtocolManager. // This is used by tests. diff --git a/chromium/components/safe_browsing_db/v4_local_database_manager.cc b/chromium/components/safe_browsing_db/v4_local_database_manager.cc index 6644f662d80..02617ce96cd 100644 --- a/chromium/components/safe_browsing_db/v4_local_database_manager.cc +++ b/chromium/components/safe_browsing_db/v4_local_database_manager.cc @@ -256,7 +256,7 @@ bool V4LocalDatabaseManager::CheckResourceUrl(const GURL& url, Client* client) { StoresToCheck stores_to_check({GetChromeUrlClientIncidentId()}); - if (!CanCheckUrl(url) || !AreStoresAvailableNow(stores_to_check)) { + if (!CanCheckUrl(url) || !AreAllStoresAvailableNow(stores_to_check)) { // Fail open: Mark resource as safe immediately. // TODO(nparker): This should queue the request if the DB isn't yet // loaded, and later decide if this store is available. @@ -276,8 +276,9 @@ bool V4LocalDatabaseManager::CheckUrlForSubresourceFilter(const GURL& url, Client* client) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - StoresToCheck stores_to_check({GetUrlSubresourceFilterId()}); - if (!AreStoresAvailableNow(stores_to_check) || !CanCheckUrl(url)) { + StoresToCheck stores_to_check( + {GetUrlSocEngId(), GetUrlSubresourceFilterId()}); + if (!AreAnyStoresAvailableNow(stores_to_check) || !CanCheckUrl(url)) { return true; } @@ -292,7 +293,7 @@ bool V4LocalDatabaseManager::MatchCsdWhitelistUrl(const GURL& url) { DCHECK_CURRENTLY_ON(BrowserThread::IO); StoresToCheck stores_to_check({GetUrlCsdWhitelistId()}); - if (!AreStoresAvailableNow(stores_to_check)) { + if (!AreAllStoresAvailableNow(stores_to_check)) { // Fail open: Whitelist everything. Otherwise we may run the // CSD phishing/malware detector on popular domains and generate // undue load on the client and server. This has the effect of disabling @@ -308,7 +309,7 @@ bool V4LocalDatabaseManager::MatchDownloadWhitelistString( DCHECK_CURRENTLY_ON(BrowserThread::IO); StoresToCheck stores_to_check({GetCertCsdDownloadWhitelistId()}); - if (!AreStoresAvailableNow(stores_to_check)) { + if (!AreAllStoresAvailableNow(stores_to_check)) { // Fail close: Whitelist nothing. This may generate download-protection // pings for whitelisted binaries, but that's fine. return false; @@ -321,7 +322,7 @@ bool V4LocalDatabaseManager::MatchDownloadWhitelistUrl(const GURL& url) { DCHECK_CURRENTLY_ON(BrowserThread::IO); StoresToCheck stores_to_check({GetUrlCsdDownloadWhitelistId()}); - if (!AreStoresAvailableNow(stores_to_check)) { + if (!AreAllStoresAvailableNow(stores_to_check)) { // Fail close: Whitelist nothing. This may generate download-protection // pings for whitelisted domains, but that's fine. return false; @@ -351,7 +352,7 @@ bool V4LocalDatabaseManager::MatchModuleWhitelistString( DCHECK_CURRENTLY_ON(BrowserThread::IO); StoresToCheck stores_to_check({GetChromeFilenameClientIncidentId()}); - if (!AreStoresAvailableNow(stores_to_check)) { + if (!AreAllStoresAvailableNow(stores_to_check)) { // Fail open: Whitelist everything. This has the effect of marking // all DLLs as safe until the DB is synced and loaded. return true; @@ -757,10 +758,16 @@ void V4LocalDatabaseManager::UpdateRequestCompleted( db_updated_callback_); } -bool V4LocalDatabaseManager::AreStoresAvailableNow( +bool V4LocalDatabaseManager::AreAllStoresAvailableNow( const StoresToCheck& stores_to_check) const { return enabled_ && v4_database_ && - v4_database_->AreStoresAvailable(stores_to_check); + v4_database_->AreAllStoresAvailable(stores_to_check); +} + +bool V4LocalDatabaseManager::AreAnyStoresAvailableNow( + const StoresToCheck& stores_to_check) const { + return enabled_ && v4_database_ && + v4_database_->AreAnyStoresAvailable(stores_to_check); } } // namespace safe_browsing diff --git a/chromium/components/safe_browsing_db/v4_local_database_manager.h b/chromium/components/safe_browsing_db/v4_local_database_manager.h index e010dee3cef..9e3ea4fa00f 100644 --- a/chromium/components/safe_browsing_db/v4_local_database_manager.h +++ b/chromium/components/safe_browsing_db/v4_local_database_manager.h @@ -272,7 +272,11 @@ class V4LocalDatabaseManager : public SafeBrowsingDatabaseManager { // Return true if we're enabled and have loaded real data for all of // these stores. - bool AreStoresAvailableNow(const StoresToCheck& stores_to_check) const; + bool AreAllStoresAvailableNow(const StoresToCheck& stores_to_check) const; + + // Return true if we're enabled and have loaded real data for any of + // these stores. + bool AreAnyStoresAvailableNow(const StoresToCheck& stores_to_check) const; // The base directory under which to create the files that contain hashes. const base::FilePath base_path_; diff --git a/chromium/components/safe_browsing_db/v4_local_database_manager_unittest.cc b/chromium/components/safe_browsing_db/v4_local_database_manager_unittest.cc index 595feec8aa7..34cb4ac5887 100644 --- a/chromium/components/safe_browsing_db/v4_local_database_manager_unittest.cc +++ b/chromium/components/safe_browsing_db/v4_local_database_manager_unittest.cc @@ -6,6 +6,7 @@ #include "base/files/scoped_temp_dir.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" +#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/test/test_simple_task_runner.h" #include "base/threading/thread_task_runner_handle.h" @@ -119,7 +120,13 @@ class FakeV4Database : public V4Database { } } - bool AreStoresAvailable(const StoresToCheck& stores_to_check) const override { + bool AreAllStoresAvailable( + const StoresToCheck& stores_to_check) const override { + return stores_available_; + } + + bool AreAnyStoresAvailable( + const StoresToCheck& stores_to_check) const override { return stores_available_; } diff --git a/chromium/components/safe_browsing_db/v4_protocol_manager_util.cc b/chromium/components/safe_browsing_db/v4_protocol_manager_util.cc index 9a97b0e4229..bd097a72b58 100644 --- a/chromium/components/safe_browsing_db/v4_protocol_manager_util.cc +++ b/chromium/components/safe_browsing_db/v4_protocol_manager_util.cc @@ -5,6 +5,7 @@ #include "components/safe_browsing_db/v4_protocol_manager_util.h" #include "base/base64.h" +#include "base/hash.h" #include "base/metrics/histogram_macros.h" #include "base/rand_util.h" #include "base/sha1.h" @@ -304,7 +305,7 @@ bool V4ProtocolManagerUtil::FullHashToHashPrefix(const FullHash& full_hash, if (full_hash.size() < prefix_size) { return false; } - *hash_prefix = full_hash.substr(prefix_size); + *hash_prefix = full_hash.substr(0, prefix_size); return true; } diff --git a/chromium/components/safe_browsing_db/v4_protocol_manager_util_unittest.cc b/chromium/components/safe_browsing_db/v4_protocol_manager_util_unittest.cc index 0680d3cc060..8018a9a896f 100644 --- a/chromium/components/safe_browsing_db/v4_protocol_manager_util_unittest.cc +++ b/chromium/components/safe_browsing_db/v4_protocol_manager_util_unittest.cc @@ -269,4 +269,28 @@ TEST_F(V4ProtocolManagerUtilTest, TestIPAddressToEncodedIPV6) { } } +TEST_F(V4ProtocolManagerUtilTest, TestFullHashToHashPrefix) { + const std::string full_hash = "abcdefgh"; + std::vector<std::tuple<bool, std::string, PrefixSize, std::string>> + test_cases = { + std::make_tuple(true, "", 0, ""), + std::make_tuple(false, "", kMinHashPrefixLength, ""), + std::make_tuple(true, "a", 1, full_hash), + std::make_tuple(true, "abcd", kMinHashPrefixLength, full_hash), + std::make_tuple(true, "abcde", kMinHashPrefixLength + 1, full_hash)}; + for (size_t i = 0; i < test_cases.size(); i++) { + DVLOG(1) << "Running case: " << i; + bool success = std::get<0>(test_cases[i]); + const auto& expected_prefix = std::get<1>(test_cases[i]); + const PrefixSize& prefix_size = std::get<2>(test_cases[i]); + const auto& input_full_hash = std::get<3>(test_cases[i]); + std::string prefix; + ASSERT_EQ(success, V4ProtocolManagerUtil::FullHashToHashPrefix( + input_full_hash, prefix_size, &prefix)); + if (success) { + ASSERT_EQ(expected_prefix, prefix); + } + } +} + } // namespace safe_browsing diff --git a/chromium/components/safe_browsing_db/v4_update_protocol_manager.cc b/chromium/components/safe_browsing_db/v4_update_protocol_manager.cc index e72eb44c029..3d485bdd6bf 100644 --- a/chromium/components/safe_browsing_db/v4_update_protocol_manager.cc +++ b/chromium/components/safe_browsing_db/v4_update_protocol_manager.cc @@ -17,6 +17,7 @@ #include "net/base/load_flags.h" #include "net/http/http_response_headers.h" #include "net/http/http_status_code.h" +#include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_fetcher.h" #include "net/url_request/url_request_context_getter.h" @@ -311,8 +312,37 @@ void V4UpdateProtocolManager::IssueUpdateRequest() { net::HttpRequestHeaders headers; GetUpdateUrlAndHeaders(req_base64, &update_url, &headers); - std::unique_ptr<net::URLFetcher> fetcher = net::URLFetcher::Create( - url_fetcher_id_++, update_url, net::URLFetcher::GET, this); + net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("safe_browsing_g4_update", R"( + semantics { + sender: "Safe Browsing" + description: + "Safe Browsing issues a request to Google every 30 minutes or so " + "to get the latest database of hashes of bad URLs." + trigger: + "On a timer, approximately every 30 minutes." + data: + "The state of the local DB is sent so the server can send just " + "the changes. This doesn't include any user data." + destination: GOOGLE_OWNED_SERVICE + } + policy { + cookies_allowed: true + cookies_store: "Safe Browsing cookie store" + setting: + "Users can disable Safe Browsing by unchecking 'Protect you and " + "your device from dangerous sites' in Chromium settings under " + "Privacy. The feature is enabled by default." + chrome_policy { + SafeBrowsingEnabled { + policy_options {mode: MANDATORY} + SafeBrowsingEnabled: false + } + } + })"); + std::unique_ptr<net::URLFetcher> fetcher = + net::URLFetcher::Create(url_fetcher_id_++, update_url, + net::URLFetcher::GET, this, traffic_annotation); fetcher->SetExtraRequestHeaders(headers.ToString()); data_use_measurement::DataUseUserData::AttachToFetcher( fetcher.get(), data_use_measurement::DataUseUserData::SAFE_BROWSING); diff --git a/chromium/components/safe_browsing_db/v4_update_protocol_manager.h b/chromium/components/safe_browsing_db/v4_update_protocol_manager.h index 4405742938c..5c60a0c398d 100644 --- a/chromium/components/safe_browsing_db/v4_update_protocol_manager.h +++ b/chromium/components/safe_browsing_db/v4_update_protocol_manager.h @@ -21,7 +21,7 @@ #include "base/threading/non_thread_safe.h" #include "base/time/time.h" #include "base/timer/timer.h" -#include "components/safe_browsing_db/safe_browsing_prefs.h" +#include "components/safe_browsing/common/safe_browsing_prefs.h" #include "components/safe_browsing_db/safebrowsing.pb.h" #include "components/safe_browsing_db/util.h" #include "components/safe_browsing_db/v4_protocol_manager_util.h" |