OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/safe_browsing_db/v4_get_hash_protocol_manager.h" | 5 #include "components/safe_browsing_db/v4_get_hash_protocol_manager.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/base64.h" | 10 #include "base/base64.h" |
11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
| 12 #include "base/run_loop.h" |
12 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
13 #include "base/test/simple_test_clock.h" | 14 #include "base/test/simple_test_clock.h" |
14 #include "base/time/time.h" | 15 #include "base/time/time.h" |
15 #include "components/safe_browsing_db/safebrowsing.pb.h" | 16 #include "components/safe_browsing_db/safebrowsing.pb.h" |
16 #include "components/safe_browsing_db/testing_util.h" | 17 #include "components/safe_browsing_db/testing_util.h" |
17 #include "components/safe_browsing_db/util.h" | 18 #include "components/safe_browsing_db/util.h" |
18 #include "net/base/escape.h" | 19 #include "net/base/escape.h" |
19 #include "net/base/load_flags.h" | 20 #include "net/base/load_flags.h" |
20 #include "net/base/net_errors.h" | 21 #include "net/base/net_errors.h" |
21 #include "net/url_request/test_url_fetcher_factory.h" | 22 #include "net/url_request/test_url_fetcher_factory.h" |
22 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
23 | 24 |
24 using base::Time; | 25 using base::Time; |
25 using base::TimeDelta; | 26 using base::TimeDelta; |
26 | 27 |
27 namespace { | 28 namespace { |
28 | 29 |
29 const char kClient[] = "unittest"; | 30 const char kClient[] = "unittest"; |
30 const char kAppVer[] = "1.0"; | 31 const char kAppVer[] = "1.0"; |
31 const char kKeyParam[] = "test_key_param"; | 32 const char kKeyParam[] = "test_key_param"; |
32 | 33 |
33 } // namespace | 34 } // namespace |
34 | 35 |
35 namespace safe_browsing { | 36 namespace safe_browsing { |
36 | 37 |
37 class SafeBrowsingV4GetHashProtocolManagerTest : public testing::Test { | 38 class V4GetHashProtocolManagerTest : public testing::Test { |
38 protected: | 39 protected: |
39 std::unique_ptr<V4GetHashProtocolManager> CreateProtocolManager() { | 40 std::unique_ptr<V4GetHashProtocolManager> CreateProtocolManager() { |
40 V4ProtocolConfig config; | 41 V4ProtocolConfig config; |
41 config.client_name = kClient; | 42 config.client_name = kClient; |
42 config.version = kAppVer; | 43 config.version = kAppVer; |
43 config.key_param = kKeyParam; | 44 config.key_param = kKeyParam; |
44 return std::unique_ptr<V4GetHashProtocolManager>( | 45 base::hash_set<UpdateListIdentifier> stores_to_look( |
45 V4GetHashProtocolManager::Create(NULL, config)); | 46 {GetUrlMalwareId(), GetChromeUrlApiId()}); |
| 47 return V4GetHashProtocolManager::Create(NULL, stores_to_look, config); |
| 48 } |
| 49 |
| 50 void SetupFetcherToReturnStockOKResponse( |
| 51 const net::TestURLFetcherFactory& factory) { |
| 52 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); |
| 53 DCHECK(fetcher); |
| 54 fetcher->set_status(net::URLRequestStatus()); |
| 55 fetcher->set_response_code(200); |
| 56 fetcher->SetResponseString(GetStockV4HashResponse()); |
| 57 fetcher->delegate()->OnURLFetchComplete(fetcher); |
46 } | 58 } |
47 | 59 |
48 std::string GetStockV4HashResponse() { | 60 std::string GetStockV4HashResponse() { |
49 FindFullHashesResponse res; | 61 FindFullHashesResponse res; |
50 res.mutable_negative_cache_duration()->set_seconds(600); | 62 res.mutable_negative_cache_duration()->set_seconds(600); |
51 ThreatMatch* m = res.add_matches(); | 63 ThreatMatch* m = res.add_matches(); |
52 m->set_threat_type(API_ABUSE); | 64 m->set_threat_type(API_ABUSE); |
53 m->set_platform_type(CHROME_PLATFORM); | 65 m->set_platform_type(CHROME_PLATFORM); |
54 m->set_threat_entry_type(URL); | 66 m->set_threat_entry_type(URL); |
55 m->mutable_cache_duration()->set_seconds(300); | 67 m->mutable_cache_duration()->set_seconds(300); |
56 m->mutable_threat()->set_hash( | 68 m->mutable_threat()->set_hash(FullHash("Everything's shiny, Cap'n.")); |
57 SBFullHashToString(SBFullHashForString("Everything's shiny, Cap'n."))); | |
58 ThreatEntryMetadata::MetadataEntry* e = | 69 ThreatEntryMetadata::MetadataEntry* e = |
59 m->mutable_threat_entry_metadata()->add_entries(); | 70 m->mutable_threat_entry_metadata()->add_entries(); |
60 e->set_key("permission"); | 71 e->set_key("permission"); |
61 e->set_value("NOTIFICATIONS"); | 72 e->set_value("NOTIFICATIONS"); |
62 | 73 |
63 // Serialize. | 74 // Serialize. |
64 std::string res_data; | 75 std::string res_data; |
65 res.SerializeToString(&res_data); | 76 res.SerializeToString(&res_data); |
66 | 77 |
67 return res_data; | 78 return res_data; |
68 } | 79 } |
69 | 80 |
70 void SetTestClock(base::Time now, V4GetHashProtocolManager* pm) { | 81 void SetTestClock(base::Time now, V4GetHashProtocolManager* pm) { |
71 base::SimpleTestClock* clock = new base::SimpleTestClock(); | 82 base::SimpleTestClock* clock = new base::SimpleTestClock(); |
72 clock->SetNow(now); | 83 clock->SetNow(now); |
73 pm->SetClockForTests(base::WrapUnique(clock)); | 84 pm->SetClockForTests(base::WrapUnique(clock)); |
74 } | 85 } |
75 }; | 86 }; |
76 | 87 |
77 void ValidateGetV4HashResults( | 88 void ValidateGetV4HashResults(const std::vector<FullHashInfo>& expected_results, |
78 const std::vector<SBFullHashResult>& expected_full_hashes, | 89 const std::vector<FullHashInfo>& actual_results) { |
79 const base::Time& expected_cache_expire, | 90 EXPECT_EQ(expected_results.size(), actual_results.size()); |
80 const std::vector<SBFullHashResult>& full_hashes, | 91 for (size_t i = 0; i < actual_results.size(); i++) { |
81 const base::Time& cache_expire) { | 92 EXPECT_TRUE(expected_results[i] == actual_results[i]); |
82 EXPECT_EQ(expected_cache_expire, cache_expire); | |
83 ASSERT_EQ(expected_full_hashes.size(), full_hashes.size()); | |
84 | |
85 for (unsigned int i = 0; i < expected_full_hashes.size(); ++i) { | |
86 const SBFullHashResult& expected = expected_full_hashes[i]; | |
87 const SBFullHashResult& actual = full_hashes[i]; | |
88 EXPECT_TRUE(SBFullHashEqual(expected.hash, actual.hash)); | |
89 EXPECT_EQ(expected.metadata, actual.metadata); | |
90 EXPECT_EQ(expected.cache_expire_after, actual.cache_expire_after); | |
91 } | 93 } |
92 } | 94 } |
93 | 95 |
94 TEST_F(SafeBrowsingV4GetHashProtocolManagerTest, | 96 TEST_F(V4GetHashProtocolManagerTest, TestGetHashErrorHandlingNetwork) { |
95 TestGetHashErrorHandlingNetwork) { | |
96 net::TestURLFetcherFactory factory; | 97 net::TestURLFetcherFactory factory; |
97 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); | 98 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); |
98 | 99 |
99 std::vector<SBPrefix> prefixes; | 100 FullHashToStoreAndHashPrefixesMap full_hash_to_store_and_hash_prefixes; |
100 std::vector<SBFullHashResult> expected_full_hashes; | 101 full_hash_to_store_and_hash_prefixes[FullHash("AFullHash")].push_back( |
101 base::Time expected_cache_expire; | 102 StoreAndHashPrefix(GetUrlSocEngId(), HashPrefix("AHashPrefix"))); |
102 | 103 std::vector<FullHashInfo> expected_results; |
103 pm->GetFullHashesWithApis( | 104 pm->GetFullHashes(full_hash_to_store_and_hash_prefixes, |
104 prefixes, base::Bind(&ValidateGetV4HashResults, expected_full_hashes, | 105 base::Bind(&ValidateGetV4HashResults, expected_results)); |
105 expected_cache_expire)); | |
106 | 106 |
107 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); | 107 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); |
108 DCHECK(fetcher); | 108 DCHECK(fetcher); |
109 // Failed request status should result in error. | 109 // Failed request status should result in error. |
110 fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED, | 110 fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED, |
111 net::ERR_CONNECTION_RESET)); | 111 net::ERR_CONNECTION_RESET)); |
112 fetcher->set_response_code(200); | 112 fetcher->set_response_code(200); |
113 fetcher->SetResponseString(GetStockV4HashResponse()); | 113 fetcher->SetResponseString(GetStockV4HashResponse()); |
114 fetcher->delegate()->OnURLFetchComplete(fetcher); | 114 fetcher->delegate()->OnURLFetchComplete(fetcher); |
115 | 115 |
116 // Should have recorded one error, but back off multiplier is unchanged. | 116 // Should have recorded one error, but back off multiplier is unchanged. |
117 EXPECT_EQ(1ul, pm->gethash_error_count_); | 117 EXPECT_EQ(1ul, pm->gethash_error_count_); |
118 EXPECT_EQ(1ul, pm->gethash_back_off_mult_); | 118 EXPECT_EQ(1ul, pm->gethash_back_off_mult_); |
119 } | 119 } |
120 | 120 |
121 TEST_F(SafeBrowsingV4GetHashProtocolManagerTest, | 121 TEST_F(V4GetHashProtocolManagerTest, TestGetHashErrorHandlingResponseCode) { |
122 TestGetHashErrorHandlingResponseCode) { | |
123 net::TestURLFetcherFactory factory; | 122 net::TestURLFetcherFactory factory; |
124 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); | 123 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); |
125 | 124 |
126 std::vector<SBPrefix> prefixes; | 125 FullHashToStoreAndHashPrefixesMap full_hash_to_store_and_hash_prefixes; |
127 std::vector<SBFullHashResult> expected_full_hashes; | 126 full_hash_to_store_and_hash_prefixes[FullHash("AFullHash")].push_back( |
128 base::Time expected_cache_expire; | 127 StoreAndHashPrefix(GetUrlSocEngId(), HashPrefix("AHashPrefix"))); |
129 | 128 std::vector<FullHashInfo> expected_results; |
130 pm->GetFullHashesWithApis( | 129 pm->GetFullHashes(full_hash_to_store_and_hash_prefixes, |
131 prefixes, base::Bind(&ValidateGetV4HashResults, expected_full_hashes, | 130 base::Bind(&ValidateGetV4HashResults, expected_results)); |
132 expected_cache_expire)); | |
133 | 131 |
134 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); | 132 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); |
135 DCHECK(fetcher); | 133 DCHECK(fetcher); |
136 fetcher->set_status(net::URLRequestStatus()); | 134 fetcher->set_status(net::URLRequestStatus()); |
137 // Response code of anything other than 200 should result in error. | 135 // Response code of anything other than 200 should result in error. |
138 fetcher->set_response_code(204); | 136 fetcher->set_response_code(204); |
139 fetcher->SetResponseString(GetStockV4HashResponse()); | 137 fetcher->SetResponseString(GetStockV4HashResponse()); |
140 fetcher->delegate()->OnURLFetchComplete(fetcher); | 138 fetcher->delegate()->OnURLFetchComplete(fetcher); |
141 | 139 |
142 // Should have recorded one error, but back off multiplier is unchanged. | 140 // Should have recorded one error, but back off multiplier is unchanged. |
143 EXPECT_EQ(1ul, pm->gethash_error_count_); | 141 EXPECT_EQ(1ul, pm->gethash_error_count_); |
144 EXPECT_EQ(1ul, pm->gethash_back_off_mult_); | 142 EXPECT_EQ(1ul, pm->gethash_back_off_mult_); |
145 } | 143 } |
146 | 144 |
147 TEST_F(SafeBrowsingV4GetHashProtocolManagerTest, TestGetHashErrorHandlingOK) { | 145 TEST_F(V4GetHashProtocolManagerTest, TestGetHashErrorHandlingOK) { |
148 net::TestURLFetcherFactory factory; | 146 net::TestURLFetcherFactory factory; |
149 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); | 147 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); |
150 | 148 |
151 base::Time now = base::Time::UnixEpoch(); | 149 base::Time now = base::Time::UnixEpoch(); |
152 SetTestClock(now, pm.get()); | 150 SetTestClock(now, pm.get()); |
153 | 151 |
154 std::vector<SBPrefix> prefixes; | 152 HashPrefix prefix("Everything"); |
155 std::vector<SBFullHashResult> expected_full_hashes; | 153 FullHash full_hash("Everything's shiny, Cap'n."); |
156 SBFullHashResult hash_result; | 154 FullHashToStoreAndHashPrefixesMap full_hash_to_store_and_hash_prefixes; |
157 hash_result.hash = SBFullHashForString("Everything's shiny, Cap'n."); | 155 full_hash_to_store_and_hash_prefixes[full_hash].push_back( |
158 hash_result.metadata.api_permissions.insert("NOTIFICATIONS"); | 156 StoreAndHashPrefix(GetChromeUrlApiId(), prefix)); |
159 hash_result.cache_expire_after = now + base::TimeDelta::FromSeconds(300); | 157 std::vector<FullHashInfo> expected_results; |
160 expected_full_hashes.push_back(hash_result); | 158 FullHashInfo fhi(full_hash, GetChromeUrlApiId(), |
161 base::Time expected_cache_expire = now + base::TimeDelta::FromSeconds(600); | 159 now + base::TimeDelta::FromSeconds(300)); |
| 160 fhi.metadata.api_permissions.insert("NOTIFICATIONS"); |
| 161 expected_results.push_back(fhi); |
162 | 162 |
163 pm->GetFullHashesWithApis( | 163 pm->GetFullHashes(full_hash_to_store_and_hash_prefixes, |
164 prefixes, base::Bind(&ValidateGetV4HashResults, expected_full_hashes, | 164 base::Bind(&ValidateGetV4HashResults, expected_results)); |
165 expected_cache_expire)); | |
166 | 165 |
167 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); | 166 SetupFetcherToReturnStockOKResponse(factory); |
168 DCHECK(fetcher); | |
169 fetcher->set_status(net::URLRequestStatus()); | |
170 fetcher->set_response_code(200); | |
171 fetcher->SetResponseString(GetStockV4HashResponse()); | |
172 fetcher->delegate()->OnURLFetchComplete(fetcher); | |
173 | 167 |
174 // No error, back off multiplier is unchanged. | 168 // No error, back off multiplier is unchanged. |
175 EXPECT_EQ(0ul, pm->gethash_error_count_); | 169 EXPECT_EQ(0ul, pm->gethash_error_count_); |
176 EXPECT_EQ(1ul, pm->gethash_back_off_mult_); | 170 EXPECT_EQ(1ul, pm->gethash_back_off_mult_); |
| 171 |
| 172 // Verify the state of the cache. |
| 173 const FullHashCache* cache = pm->full_hash_cache_for_tests(); |
| 174 // Check the cache. |
| 175 ASSERT_EQ(1u, cache->size()); |
| 176 EXPECT_EQ(1u, cache->count(prefix)); |
| 177 const CachedHashPrefixInfo& cached_result = cache->at(prefix); |
| 178 EXPECT_EQ(cached_result.negative_ttl, |
| 179 now + base::TimeDelta::FromSeconds(600)); |
| 180 ASSERT_EQ(1u, cached_result.full_hash_infos.size()); |
| 181 EXPECT_EQ(FullHash("Everything's shiny, Cap'n."), |
| 182 cached_result.full_hash_infos[0].full_hash); |
177 } | 183 } |
178 | 184 |
179 TEST_F(SafeBrowsingV4GetHashProtocolManagerTest, TestGetHashRequest) { | 185 TEST_F(V4GetHashProtocolManagerTest, |
| 186 TestResultsNotCachedForNegativeCacheDuration) { |
| 187 net::TestURLFetcherFactory factory; |
180 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); | 188 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); |
181 | 189 |
| 190 HashPrefix prefix("Everything"); |
| 191 std::vector<HashPrefix> prefixes_requested({prefix}); |
| 192 base::Time negative_cache_expire; |
| 193 FullHash full_hash("Everything's shiny, Cap'n."); |
| 194 std::vector<FullHashInfo> fhis; |
| 195 fhis.emplace_back(full_hash, GetChromeUrlApiId(), base::Time::UnixEpoch()); |
| 196 |
| 197 pm->UpdateCache(prefixes_requested, fhis, negative_cache_expire); |
| 198 |
| 199 // Verify the state of the cache. |
| 200 const FullHashCache* cache = pm->full_hash_cache_for_tests(); |
| 201 // Check the cache. |
| 202 EXPECT_EQ(0u, cache->size()); |
| 203 } |
| 204 |
| 205 TEST_F(V4GetHashProtocolManagerTest, TestGetHashRequest) { |
| 206 HashPrefix one = "hashone"; |
| 207 HashPrefix two = "hashtwo"; |
| 208 std::vector<HashPrefix> prefixes_to_request = {one, two}; |
| 209 |
182 FindFullHashesRequest req; | 210 FindFullHashesRequest req; |
183 ThreatInfo* info = req.mutable_threat_info(); | 211 ThreatInfo* info = req.mutable_threat_info(); |
| 212 info->add_threat_types(MALWARE_THREAT); |
184 info->add_threat_types(API_ABUSE); | 213 info->add_threat_types(API_ABUSE); |
| 214 |
| 215 info->add_platform_types(GetCurrentPlatformType()); |
185 info->add_platform_types(CHROME_PLATFORM); | 216 info->add_platform_types(CHROME_PLATFORM); |
| 217 |
186 info->add_threat_entry_types(URL); | 218 info->add_threat_entry_types(URL); |
187 | 219 |
188 SBPrefix one = 1u; | 220 info->add_threat_entries()->set_hash(one); |
189 SBPrefix two = 2u; | 221 info->add_threat_entries()->set_hash(two); |
190 SBPrefix three = 3u; | |
191 std::string hash(reinterpret_cast<const char*>(&one), sizeof(SBPrefix)); | |
192 info->add_threat_entries()->set_hash(hash); | |
193 hash.clear(); | |
194 hash.append(reinterpret_cast<const char*>(&two), sizeof(SBPrefix)); | |
195 info->add_threat_entries()->set_hash(hash); | |
196 hash.clear(); | |
197 hash.append(reinterpret_cast<const char*>(&three), sizeof(SBPrefix)); | |
198 info->add_threat_entries()->set_hash(hash); | |
199 | 222 |
200 // Serialize and Base64 encode. | 223 // Serialize and Base64 encode. |
201 std::string req_data, req_base64; | 224 std::string req_data, req_base64; |
202 req.SerializeToString(&req_data); | 225 req.SerializeToString(&req_data); |
203 base::Base64Encode(req_data, &req_base64); | 226 base::Base64Encode(req_data, &req_base64); |
204 | 227 |
205 std::vector<PlatformType> platform; | 228 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); |
206 platform.push_back(CHROME_PLATFORM); | 229 EXPECT_EQ(req_base64, pm->GetHashRequest(prefixes_to_request)); |
207 std::vector<SBPrefix> prefixes; | |
208 prefixes.push_back(one); | |
209 prefixes.push_back(two); | |
210 prefixes.push_back(three); | |
211 EXPECT_EQ(req_base64, pm->GetHashRequest(prefixes, platform, API_ABUSE)); | |
212 } | 230 } |
213 | 231 |
214 TEST_F(SafeBrowsingV4GetHashProtocolManagerTest, TestParseHashResponse) { | 232 TEST_F(V4GetHashProtocolManagerTest, TestParseHashResponse) { |
215 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); | 233 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); |
216 | 234 |
217 base::Time now = base::Time::UnixEpoch(); | 235 base::Time now = base::Time::UnixEpoch(); |
218 SetTestClock(now, pm.get()); | 236 SetTestClock(now, pm.get()); |
219 | 237 |
| 238 FullHash full_hash("Everything's shiny, Cap'n."); |
220 FindFullHashesResponse res; | 239 FindFullHashesResponse res; |
221 res.mutable_negative_cache_duration()->set_seconds(600); | 240 res.mutable_negative_cache_duration()->set_seconds(600); |
222 res.mutable_minimum_wait_duration()->set_seconds(400); | 241 res.mutable_minimum_wait_duration()->set_seconds(400); |
223 ThreatMatch* m = res.add_matches(); | 242 ThreatMatch* m = res.add_matches(); |
224 m->set_threat_type(API_ABUSE); | 243 m->set_threat_type(API_ABUSE); |
225 m->set_platform_type(CHROME_PLATFORM); | 244 m->set_platform_type(CHROME_PLATFORM); |
226 m->set_threat_entry_type(URL); | 245 m->set_threat_entry_type(URL); |
227 m->mutable_cache_duration()->set_seconds(300); | 246 m->mutable_cache_duration()->set_seconds(300); |
228 m->mutable_threat()->set_hash( | 247 m->mutable_threat()->set_hash(full_hash); |
229 SBFullHashToString(SBFullHashForString("Everything's shiny, Cap'n."))); | |
230 ThreatEntryMetadata::MetadataEntry* e = | 248 ThreatEntryMetadata::MetadataEntry* e = |
231 m->mutable_threat_entry_metadata()->add_entries(); | 249 m->mutable_threat_entry_metadata()->add_entries(); |
232 e->set_key("permission"); | 250 e->set_key("permission"); |
233 e->set_value("NOTIFICATIONS"); | 251 e->set_value("NOTIFICATIONS"); |
234 | 252 |
235 // Serialize. | 253 // Serialize. |
236 std::string res_data; | 254 std::string res_data; |
237 res.SerializeToString(&res_data); | 255 res.SerializeToString(&res_data); |
238 | 256 |
239 std::vector<SBFullHashResult> full_hashes; | 257 std::vector<FullHashInfo> full_hash_infos; |
240 base::Time cache_expire; | 258 base::Time cache_expire; |
241 EXPECT_TRUE(pm->ParseHashResponse(res_data, &full_hashes, &cache_expire)); | 259 EXPECT_TRUE(pm->ParseHashResponse(res_data, &full_hash_infos, &cache_expire)); |
242 | 260 |
243 EXPECT_EQ(now + base::TimeDelta::FromSeconds(600), cache_expire); | 261 EXPECT_EQ(now + base::TimeDelta::FromSeconds(600), cache_expire); |
244 EXPECT_EQ(1ul, full_hashes.size()); | 262 ASSERT_EQ(1ul, full_hash_infos.size()); |
245 EXPECT_TRUE(SBFullHashEqual(SBFullHashForString("Everything's shiny, Cap'n."), | 263 const FullHashInfo& fhi = full_hash_infos[0]; |
246 full_hashes[0].hash)); | 264 EXPECT_EQ(full_hash, fhi.full_hash); |
247 EXPECT_EQ(1ul, full_hashes[0].metadata.api_permissions.size()); | 265 EXPECT_EQ(GetChromeUrlApiId(), fhi.list_id); |
248 EXPECT_EQ(1ul, | 266 EXPECT_EQ(1ul, fhi.metadata.api_permissions.size()); |
249 full_hashes[0].metadata.api_permissions.count("NOTIFICATIONS")); | 267 EXPECT_EQ(1ul, fhi.metadata.api_permissions.count("NOTIFICATIONS")); |
250 EXPECT_EQ(now + | 268 EXPECT_EQ(now + base::TimeDelta::FromSeconds(300), fhi.positive_ttl); |
251 base::TimeDelta::FromSeconds(300), full_hashes[0].cache_expire_after); | |
252 EXPECT_EQ(now + base::TimeDelta::FromSeconds(400), pm->next_gethash_time_); | 269 EXPECT_EQ(now + base::TimeDelta::FromSeconds(400), pm->next_gethash_time_); |
253 } | 270 } |
254 | 271 |
255 // Adds an entry with an ignored ThreatEntryType. | 272 // Adds an entry with an ignored ThreatEntryType. |
256 TEST_F(SafeBrowsingV4GetHashProtocolManagerTest, | 273 TEST_F(V4GetHashProtocolManagerTest, |
257 TestParseHashResponseWrongThreatEntryType) { | 274 TestParseHashResponseWrongThreatEntryType) { |
258 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); | 275 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); |
259 | 276 |
260 base::Time now = base::Time::UnixEpoch(); | 277 base::Time now = base::Time::UnixEpoch(); |
261 SetTestClock(now, pm.get()); | 278 SetTestClock(now, pm.get()); |
262 | 279 |
263 FindFullHashesResponse res; | 280 FindFullHashesResponse res; |
264 res.mutable_negative_cache_duration()->set_seconds(600); | 281 res.mutable_negative_cache_duration()->set_seconds(600); |
265 res.add_matches()->set_threat_entry_type(EXECUTABLE); | 282 res.add_matches()->set_threat_entry_type(EXECUTABLE); |
266 | 283 |
267 // Serialize. | 284 // Serialize. |
268 std::string res_data; | 285 std::string res_data; |
269 res.SerializeToString(&res_data); | 286 res.SerializeToString(&res_data); |
270 | 287 |
271 std::vector<SBFullHashResult> full_hashes; | 288 std::vector<FullHashInfo> full_hash_infos; |
272 base::Time cache_expire; | 289 base::Time cache_expire; |
273 EXPECT_FALSE(pm->ParseHashResponse(res_data, &full_hashes, &cache_expire)); | 290 EXPECT_FALSE( |
| 291 pm->ParseHashResponse(res_data, &full_hash_infos, &cache_expire)); |
274 | 292 |
275 EXPECT_EQ(now + base::TimeDelta::FromSeconds(600), cache_expire); | 293 EXPECT_EQ(now + base::TimeDelta::FromSeconds(600), cache_expire); |
276 // There should be no hash results. | 294 // There should be no hash results. |
277 EXPECT_EQ(0ul, full_hashes.size()); | 295 EXPECT_EQ(0ul, full_hash_infos.size()); |
278 } | 296 } |
279 | 297 |
280 // Adds entries with a ThreatPatternType metadata. | 298 // Adds entries with a ThreatPatternType metadata. |
281 TEST_F(SafeBrowsingV4GetHashProtocolManagerTest, | 299 TEST_F(V4GetHashProtocolManagerTest, TestParseHashThreatPatternType) { |
282 TestParseHashThreatPatternType) { | |
283 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); | 300 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); |
284 | 301 |
285 base::Time now = base::Time::UnixEpoch(); | 302 base::Time now = base::Time::UnixEpoch(); |
286 SetTestClock(now, pm.get()); | 303 SetTestClock(now, pm.get()); |
287 | 304 |
288 // Test social engineering pattern type. | 305 { |
289 FindFullHashesResponse se_res; | 306 // Test social engineering pattern type. |
290 se_res.mutable_negative_cache_duration()->set_seconds(600); | 307 FindFullHashesResponse se_res; |
291 ThreatMatch* se = se_res.add_matches(); | 308 se_res.mutable_negative_cache_duration()->set_seconds(600); |
292 se->set_threat_type(SOCIAL_ENGINEERING_PUBLIC); | 309 ThreatMatch* se = se_res.add_matches(); |
293 se->set_platform_type(CHROME_PLATFORM); | 310 se->set_threat_type(SOCIAL_ENGINEERING_PUBLIC); |
294 se->set_threat_entry_type(URL); | 311 se->set_platform_type(CHROME_PLATFORM); |
295 SBFullHash hash_string = SBFullHashForString("Everything's shiny, Cap'n."); | 312 se->set_threat_entry_type(URL); |
296 se->mutable_threat()->set_hash(SBFullHashToString(hash_string)); | 313 FullHash full_hash("Everything's shiny, Cap'n."); |
297 ThreatEntryMetadata::MetadataEntry* se_meta = | 314 se->mutable_threat()->set_hash(full_hash); |
298 se->mutable_threat_entry_metadata()->add_entries(); | 315 ThreatEntryMetadata::MetadataEntry* se_meta = |
299 se_meta->set_key("se_pattern_type"); | 316 se->mutable_threat_entry_metadata()->add_entries(); |
300 se_meta->set_value("SOCIAL_ENGINEERING_LANDING"); | 317 se_meta->set_key("se_pattern_type"); |
| 318 se_meta->set_value("SOCIAL_ENGINEERING_LANDING"); |
301 | 319 |
302 std::string se_data; | 320 std::string se_data; |
303 se_res.SerializeToString(&se_data); | 321 se_res.SerializeToString(&se_data); |
304 | 322 |
305 std::vector<SBFullHashResult> full_hashes; | 323 std::vector<FullHashInfo> full_hash_infos; |
306 base::Time cache_expire; | 324 base::Time cache_expire; |
307 EXPECT_TRUE(pm->ParseHashResponse(se_data, &full_hashes, &cache_expire)); | 325 EXPECT_TRUE( |
| 326 pm->ParseHashResponse(se_data, &full_hash_infos, &cache_expire)); |
| 327 EXPECT_EQ(now + base::TimeDelta::FromSeconds(600), cache_expire); |
308 | 328 |
309 EXPECT_EQ(now + base::TimeDelta::FromSeconds(600), cache_expire); | 329 ASSERT_EQ(1ul, full_hash_infos.size()); |
310 EXPECT_EQ(1ul, full_hashes.size()); | 330 const FullHashInfo& fhi = full_hash_infos[0]; |
311 EXPECT_TRUE(SBFullHashEqual(hash_string, full_hashes[0].hash)); | 331 EXPECT_EQ(full_hash, fhi.full_hash); |
312 EXPECT_EQ(ThreatPatternType::SOCIAL_ENGINEERING_LANDING, | 332 const UpdateListIdentifier list_id(CHROME_PLATFORM, URL, |
313 full_hashes[0].metadata.threat_pattern_type); | 333 SOCIAL_ENGINEERING_PUBLIC); |
| 334 EXPECT_EQ(list_id, fhi.list_id); |
| 335 EXPECT_EQ(ThreatPatternType::SOCIAL_ENGINEERING_LANDING, |
| 336 fhi.metadata.threat_pattern_type); |
| 337 } |
314 | 338 |
315 // Test potentially harmful application pattern type. | 339 { |
316 FindFullHashesResponse pha_res; | 340 // Test potentially harmful application pattern type. |
317 pha_res.mutable_negative_cache_duration()->set_seconds(600); | 341 FindFullHashesResponse pha_res; |
318 ThreatMatch* pha = pha_res.add_matches(); | 342 pha_res.mutable_negative_cache_duration()->set_seconds(600); |
319 pha->set_threat_type(POTENTIALLY_HARMFUL_APPLICATION); | 343 ThreatMatch* pha = pha_res.add_matches(); |
320 pha->set_threat_entry_type(URL); | 344 pha->set_threat_type(POTENTIALLY_HARMFUL_APPLICATION); |
321 pha->set_platform_type(CHROME_PLATFORM); | 345 pha->set_threat_entry_type(URL); |
322 hash_string = SBFullHashForString("Not to fret."); | 346 pha->set_platform_type(CHROME_PLATFORM); |
323 pha->mutable_threat()->set_hash(SBFullHashToString(hash_string)); | 347 FullHash full_hash("Not to fret."); |
324 ThreatEntryMetadata::MetadataEntry* pha_meta = | 348 pha->mutable_threat()->set_hash(full_hash); |
325 pha->mutable_threat_entry_metadata()->add_entries(); | 349 ThreatEntryMetadata::MetadataEntry* pha_meta = |
326 pha_meta->set_key("pha_pattern_type"); | 350 pha->mutable_threat_entry_metadata()->add_entries(); |
327 pha_meta->set_value("LANDING"); | 351 pha_meta->set_key("pha_pattern_type"); |
| 352 pha_meta->set_value("LANDING"); |
328 | 353 |
329 std::string pha_data; | 354 std::string pha_data; |
330 pha_res.SerializeToString(&pha_data); | 355 pha_res.SerializeToString(&pha_data); |
331 full_hashes.clear(); | 356 std::vector<FullHashInfo> full_hash_infos; |
332 EXPECT_TRUE(pm->ParseHashResponse(pha_data, &full_hashes, &cache_expire)); | 357 base::Time cache_expire; |
333 EXPECT_EQ(1ul, full_hashes.size()); | 358 EXPECT_TRUE( |
334 EXPECT_TRUE(SBFullHashEqual(hash_string, full_hashes[0].hash)); | 359 pm->ParseHashResponse(pha_data, &full_hash_infos, &cache_expire)); |
335 EXPECT_EQ(ThreatPatternType::MALWARE_LANDING, | 360 EXPECT_EQ(now + base::TimeDelta::FromSeconds(600), cache_expire); |
336 full_hashes[0].metadata.threat_pattern_type); | |
337 | 361 |
338 // Test invalid pattern type. | 362 ASSERT_EQ(1ul, full_hash_infos.size()); |
339 FindFullHashesResponse invalid_res; | 363 const FullHashInfo& fhi = full_hash_infos[0]; |
340 invalid_res.mutable_negative_cache_duration()->set_seconds(600); | 364 EXPECT_EQ(full_hash, fhi.full_hash); |
341 ThreatMatch* invalid = invalid_res.add_matches(); | 365 const UpdateListIdentifier list_id(CHROME_PLATFORM, URL, |
342 invalid->set_threat_type(POTENTIALLY_HARMFUL_APPLICATION); | 366 POTENTIALLY_HARMFUL_APPLICATION); |
343 invalid->set_threat_entry_type(URL); | 367 EXPECT_EQ(list_id, fhi.list_id); |
344 invalid->set_platform_type(CHROME_PLATFORM); | 368 EXPECT_EQ(ThreatPatternType::MALWARE_LANDING, |
345 invalid->mutable_threat()->set_hash(SBFullHashToString(hash_string)); | 369 fhi.metadata.threat_pattern_type); |
346 ThreatEntryMetadata::MetadataEntry* invalid_meta = | 370 } |
347 invalid->mutable_threat_entry_metadata()->add_entries(); | |
348 invalid_meta->set_key("pha_pattern_type"); | |
349 invalid_meta->set_value("INVALIDE_VALUE"); | |
350 | 371 |
351 std::string invalid_data; | 372 { |
352 invalid_res.SerializeToString(&invalid_data); | 373 // Test invalid pattern type. |
353 full_hashes.clear(); | 374 FullHash full_hash("Not to fret."); |
354 EXPECT_FALSE( | 375 FindFullHashesResponse invalid_res; |
355 pm->ParseHashResponse(invalid_data, &full_hashes, &cache_expire)); | 376 invalid_res.mutable_negative_cache_duration()->set_seconds(600); |
356 EXPECT_EQ(0ul, full_hashes.size()); | 377 ThreatMatch* invalid = invalid_res.add_matches(); |
| 378 invalid->set_threat_type(POTENTIALLY_HARMFUL_APPLICATION); |
| 379 invalid->set_threat_entry_type(URL); |
| 380 invalid->set_platform_type(CHROME_PLATFORM); |
| 381 invalid->mutable_threat()->set_hash(full_hash); |
| 382 ThreatEntryMetadata::MetadataEntry* invalid_meta = |
| 383 invalid->mutable_threat_entry_metadata()->add_entries(); |
| 384 invalid_meta->set_key("pha_pattern_type"); |
| 385 invalid_meta->set_value("INVALIDE_VALUE"); |
| 386 |
| 387 std::string invalid_data; |
| 388 invalid_res.SerializeToString(&invalid_data); |
| 389 std::vector<FullHashInfo> full_hash_infos; |
| 390 base::Time cache_expire; |
| 391 EXPECT_FALSE( |
| 392 pm->ParseHashResponse(invalid_data, &full_hash_infos, &cache_expire)); |
| 393 EXPECT_EQ(0ul, full_hash_infos.size()); |
| 394 } |
357 } | 395 } |
358 | 396 |
359 // Adds metadata with a key value that is not "permission". | 397 // Adds metadata with a key value that is not "permission". |
360 TEST_F(SafeBrowsingV4GetHashProtocolManagerTest, | 398 TEST_F(V4GetHashProtocolManagerTest, |
361 TestParseHashResponseNonPermissionMetadata) { | 399 TestParseHashResponseNonPermissionMetadata) { |
362 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); | 400 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); |
363 | 401 |
364 base::Time now = base::Time::UnixEpoch(); | 402 base::Time now = base::Time::UnixEpoch(); |
365 SetTestClock(now, pm.get()); | 403 SetTestClock(now, pm.get()); |
366 | 404 |
367 FindFullHashesResponse res; | 405 FindFullHashesResponse res; |
368 res.mutable_negative_cache_duration()->set_seconds(600); | 406 res.mutable_negative_cache_duration()->set_seconds(600); |
369 ThreatMatch* m = res.add_matches(); | 407 ThreatMatch* m = res.add_matches(); |
370 m->set_threat_type(API_ABUSE); | 408 m->set_threat_type(API_ABUSE); |
371 m->set_platform_type(CHROME_PLATFORM); | 409 m->set_platform_type(CHROME_PLATFORM); |
372 m->set_threat_entry_type(URL); | 410 m->set_threat_entry_type(URL); |
373 m->mutable_threat()->set_hash( | 411 m->mutable_threat()->set_hash(FullHash("Not to fret.")); |
374 SBFullHashToString(SBFullHashForString("Not to fret."))); | |
375 ThreatEntryMetadata::MetadataEntry* e = | 412 ThreatEntryMetadata::MetadataEntry* e = |
376 m->mutable_threat_entry_metadata()->add_entries(); | 413 m->mutable_threat_entry_metadata()->add_entries(); |
377 e->set_key("notpermission"); | 414 e->set_key("notpermission"); |
378 e->set_value("NOTGEOLOCATION"); | 415 e->set_value("NOTGEOLOCATION"); |
379 | 416 |
380 // Serialize. | 417 // Serialize. |
381 std::string res_data; | 418 std::string res_data; |
382 res.SerializeToString(&res_data); | 419 res.SerializeToString(&res_data); |
383 | 420 |
384 std::vector<SBFullHashResult> full_hashes; | 421 std::vector<FullHashInfo> full_hash_infos; |
385 base::Time cache_expire; | 422 base::Time cache_expire; |
386 EXPECT_FALSE(pm->ParseHashResponse(res_data, &full_hashes, &cache_expire)); | 423 EXPECT_FALSE( |
| 424 pm->ParseHashResponse(res_data, &full_hash_infos, &cache_expire)); |
387 | 425 |
388 EXPECT_EQ(now + base::TimeDelta::FromSeconds(600), cache_expire); | 426 EXPECT_EQ(now + base::TimeDelta::FromSeconds(600), cache_expire); |
389 EXPECT_EQ(0ul, full_hashes.size()); | 427 EXPECT_EQ(0ul, full_hash_infos.size()); |
390 } | 428 } |
391 | 429 |
392 TEST_F(SafeBrowsingV4GetHashProtocolManagerTest, | 430 TEST_F(V4GetHashProtocolManagerTest, |
393 TestParseHashResponseInconsistentThreatTypes) { | 431 TestParseHashResponseInconsistentThreatTypes) { |
394 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); | 432 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); |
395 | 433 |
396 FindFullHashesResponse res; | 434 FindFullHashesResponse res; |
397 res.mutable_negative_cache_duration()->set_seconds(600); | 435 res.mutable_negative_cache_duration()->set_seconds(600); |
398 ThreatMatch* m1 = res.add_matches(); | 436 ThreatMatch* m1 = res.add_matches(); |
399 m1->set_threat_type(API_ABUSE); | 437 m1->set_threat_type(API_ABUSE); |
400 m1->set_platform_type(CHROME_PLATFORM); | 438 m1->set_platform_type(CHROME_PLATFORM); |
401 m1->set_threat_entry_type(URL); | 439 m1->set_threat_entry_type(URL); |
402 m1->mutable_threat()->set_hash( | 440 m1->mutable_threat()->set_hash(FullHash("Everything's shiny, Cap'n.")); |
403 SBFullHashToString(SBFullHashForString("Everything's shiny, Cap'n."))); | |
404 m1->mutable_threat_entry_metadata()->add_entries(); | 441 m1->mutable_threat_entry_metadata()->add_entries(); |
405 ThreatMatch* m2 = res.add_matches(); | 442 ThreatMatch* m2 = res.add_matches(); |
406 m2->set_threat_type(MALWARE_THREAT); | 443 m2->set_threat_type(MALWARE_THREAT); |
407 m2->set_threat_entry_type(URL); | 444 m2->set_threat_entry_type(URL); |
408 m2->mutable_threat()->set_hash( | 445 m2->mutable_threat()->set_hash(FullHash("Not to fret.")); |
409 SBFullHashToString(SBFullHashForString("Not to fret."))); | |
410 | 446 |
411 // Serialize. | 447 // Serialize. |
412 std::string res_data; | 448 std::string res_data; |
413 res.SerializeToString(&res_data); | 449 res.SerializeToString(&res_data); |
414 | 450 |
415 std::vector<SBFullHashResult> full_hashes; | 451 std::vector<FullHashInfo> full_hash_infos; |
416 base::Time cache_expire; | 452 base::Time cache_expire; |
417 EXPECT_FALSE(pm->ParseHashResponse(res_data, &full_hashes, &cache_expire)); | 453 EXPECT_FALSE( |
| 454 pm->ParseHashResponse(res_data, &full_hash_infos, &cache_expire)); |
| 455 } |
| 456 |
| 457 // Checks that results are looked up correctly in the cache. |
| 458 TEST_F(V4GetHashProtocolManagerTest, GetCachedResults) { |
| 459 base::Time now = base::Time::UnixEpoch(); |
| 460 FullHash full_hash("example.com/"); |
| 461 HashPrefix prefix("exam"); |
| 462 FullHashToStoreAndHashPrefixesMap full_hash_to_store_and_hash_prefixes; |
| 463 std::vector<HashPrefix> prefixes_to_request; |
| 464 std::vector<FullHashInfo> cached_full_hash_infos; |
| 465 full_hash_to_store_and_hash_prefixes[full_hash].push_back( |
| 466 StoreAndHashPrefix(GetUrlMalwareId(), prefix)); |
| 467 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); |
| 468 FullHashCache* cache = pm->full_hash_cache_for_tests(); |
| 469 |
| 470 // Test with an empty cache. (Case: 2) |
| 471 pm->GetFullHashCachedResults(full_hash_to_store_and_hash_prefixes, now, |
| 472 &prefixes_to_request, &cached_full_hash_infos); |
| 473 EXPECT_TRUE(cache->empty()); |
| 474 ASSERT_EQ(1ul, prefixes_to_request.size()); |
| 475 EXPECT_EQ(prefix, prefixes_to_request[0]); |
| 476 EXPECT_TRUE(cached_full_hash_infos.empty()); |
| 477 |
| 478 // Prefix has a cache entry but full hash is not there. (Case: 1-b-i) |
| 479 CachedHashPrefixInfo* entry = &(*cache)[prefix]; |
| 480 entry->negative_ttl = now + base::TimeDelta::FromMinutes(5); |
| 481 prefixes_to_request.clear(); |
| 482 cached_full_hash_infos.clear(); |
| 483 pm->GetFullHashCachedResults(full_hash_to_store_and_hash_prefixes, now, |
| 484 &prefixes_to_request, &cached_full_hash_infos); |
| 485 EXPECT_TRUE(prefixes_to_request.empty()); |
| 486 EXPECT_TRUE(cached_full_hash_infos.empty()); |
| 487 |
| 488 // Expired negative cache entry. (Case: 1-b-ii) |
| 489 entry->negative_ttl = now - base::TimeDelta::FromMinutes(5); |
| 490 prefixes_to_request.clear(); |
| 491 cached_full_hash_infos.clear(); |
| 492 pm->GetFullHashCachedResults(full_hash_to_store_and_hash_prefixes, now, |
| 493 &prefixes_to_request, &cached_full_hash_infos); |
| 494 ASSERT_EQ(1ul, prefixes_to_request.size()); |
| 495 EXPECT_EQ(prefix, prefixes_to_request[0]); |
| 496 EXPECT_TRUE(cached_full_hash_infos.empty()); |
| 497 |
| 498 // Now put unexpired full hash in the cache. (Case: 1-a-i) |
| 499 FullHashInfo fhi(full_hash, GetUrlMalwareId(), |
| 500 now + base::TimeDelta::FromMinutes(3)); |
| 501 entry->full_hash_infos.push_back(fhi); |
| 502 prefixes_to_request.clear(); |
| 503 cached_full_hash_infos.clear(); |
| 504 pm->GetFullHashCachedResults(full_hash_to_store_and_hash_prefixes, now, |
| 505 &prefixes_to_request, &cached_full_hash_infos); |
| 506 EXPECT_TRUE(prefixes_to_request.empty()); |
| 507 ASSERT_EQ(1ul, cached_full_hash_infos.size()); |
| 508 EXPECT_EQ(full_hash, cached_full_hash_infos[0].full_hash); |
| 509 |
| 510 // Expire the full hash in the cache. (Case: 1-a-ii) |
| 511 entry->full_hash_infos[0].positive_ttl = |
| 512 now - base::TimeDelta::FromMinutes(3); |
| 513 prefixes_to_request.clear(); |
| 514 cached_full_hash_infos.clear(); |
| 515 pm->GetFullHashCachedResults(full_hash_to_store_and_hash_prefixes, now, |
| 516 &prefixes_to_request, &cached_full_hash_infos); |
| 517 ASSERT_EQ(1ul, prefixes_to_request.size()); |
| 518 EXPECT_EQ(prefix, prefixes_to_request[0]); |
| 519 EXPECT_TRUE(cached_full_hash_infos.empty()); |
| 520 } |
| 521 |
| 522 TEST_F(V4GetHashProtocolManagerTest, TestUpdatesAreMerged) { |
| 523 // We'll add one of the requested FullHashInfo objects into the cache, and |
| 524 // inject the other one as a response from the server. The result should |
| 525 // include both FullHashInfo objects. |
| 526 |
| 527 net::TestURLFetcherFactory factory; |
| 528 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); |
| 529 HashPrefix prefix_1("exam"); |
| 530 FullHash full_hash_1("example.com/test"); |
| 531 HashPrefix prefix_2("Everything"); |
| 532 FullHash full_hash_2("Everything's shiny, Cap'n."); |
| 533 |
| 534 base::Time now = Time::Now(); |
| 535 SetTestClock(now, pm.get()); |
| 536 |
| 537 FullHashCache* cache = pm->full_hash_cache_for_tests(); |
| 538 CachedHashPrefixInfo* entry = &(*cache)[prefix_1]; |
| 539 entry->negative_ttl = now + base::TimeDelta::FromMinutes(100); |
| 540 // Put one unexpired full hash in the cache for a store we'll look in. |
| 541 entry->full_hash_infos.emplace_back(full_hash_1, GetUrlMalwareId(), |
| 542 now + base::TimeDelta::FromSeconds(200)); |
| 543 // Put one unexpired full hash in the cache for a store we'll not look in. |
| 544 entry->full_hash_infos.emplace_back(full_hash_1, GetUrlSocEngId(), |
| 545 now + base::TimeDelta::FromSeconds(200)); |
| 546 |
| 547 // Request full hash information from two stores. |
| 548 FullHashToStoreAndHashPrefixesMap full_hash_to_store_and_hash_prefixes; |
| 549 full_hash_to_store_and_hash_prefixes[full_hash_1].push_back( |
| 550 StoreAndHashPrefix(GetUrlMalwareId(), prefix_1)); |
| 551 full_hash_to_store_and_hash_prefixes[full_hash_2].push_back( |
| 552 StoreAndHashPrefix(GetChromeUrlApiId(), prefix_2)); |
| 553 |
| 554 // Expect full hash information from both stores. |
| 555 std::vector<FullHashInfo> expected_results; |
| 556 expected_results.emplace_back(full_hash_1, GetUrlMalwareId(), |
| 557 now + base::TimeDelta::FromSeconds(200)); |
| 558 expected_results.emplace_back(full_hash_2, GetChromeUrlApiId(), |
| 559 now + base::TimeDelta::FromSeconds(300)); |
| 560 expected_results[1].metadata.api_permissions.insert("NOTIFICATIONS"); |
| 561 |
| 562 pm->GetFullHashes(full_hash_to_store_and_hash_prefixes, |
| 563 base::Bind(&ValidateGetV4HashResults, expected_results)); |
| 564 |
| 565 SetupFetcherToReturnStockOKResponse(factory); |
| 566 |
| 567 // No error, back off multiplier is unchanged. |
| 568 EXPECT_EQ(0ul, pm->gethash_error_count_); |
| 569 EXPECT_EQ(1ul, pm->gethash_back_off_mult_); |
| 570 |
| 571 // Verify the state of the cache. |
| 572 ASSERT_EQ(2u, cache->size()); |
| 573 const CachedHashPrefixInfo& cached_result_1 = cache->at(prefix_1); |
| 574 EXPECT_EQ(cached_result_1.negative_ttl, |
| 575 now + base::TimeDelta::FromMinutes(100)); |
| 576 ASSERT_EQ(2u, cached_result_1.full_hash_infos.size()); |
| 577 EXPECT_EQ(full_hash_1, cached_result_1.full_hash_infos[0].full_hash); |
| 578 EXPECT_EQ(GetUrlMalwareId(), cached_result_1.full_hash_infos[0].list_id); |
| 579 |
| 580 const CachedHashPrefixInfo& cached_result_2 = cache->at(prefix_2); |
| 581 EXPECT_EQ(cached_result_2.negative_ttl, |
| 582 now + base::TimeDelta::FromSeconds(600)); |
| 583 ASSERT_EQ(1u, cached_result_2.full_hash_infos.size()); |
| 584 EXPECT_EQ(full_hash_2, cached_result_2.full_hash_infos[0].full_hash); |
| 585 EXPECT_EQ(GetChromeUrlApiId(), cached_result_2.full_hash_infos[0].list_id); |
418 } | 586 } |
419 | 587 |
420 } // namespace safe_browsing | 588 } // namespace safe_browsing |
OLD | NEW |