Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(326)

Side by Side Diff: chrome/browser/safe_browsing/v4_protocol_manager_unittest.cc

Issue 1658913003: SafeBrowsing: Move V4ProtocolManager to components. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@sb-v4-3
Patch Set: Add build dependency Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/safe_browsing/v4_protocol_manager.cc ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include <vector>
6
7 #include "base/base64.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/time/time.h"
11 #include "chrome/browser/safe_browsing/v4_protocol_manager.h"
12 #include "components/safe_browsing_db/safebrowsing.pb.h"
13 #include "components/safe_browsing_db/util.h"
14 #include "net/base/escape.h"
15 #include "net/base/load_flags.h"
16 #include "net/base/net_errors.h"
17 #include "net/url_request/test_url_fetcher_factory.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 using base::Time;
21 using base::TimeDelta;
22
23 namespace {
24
25 const char kClient[] = "unittest";
26 const char kAppVer[] = "1.0";
27 const char kKeyParam[] = "test_key_param";
28
29 } // namespace
30
31 namespace safe_browsing {
32
33 class SafeBrowsingV4ProtocolManagerTest : public testing::Test {
34 protected:
35
36 scoped_ptr<V4ProtocolManager> CreateProtocolManager() {
37 V4ProtocolConfig config;
38 config.client_name = kClient;
39 config.version = kAppVer;
40 config.key_param = kKeyParam;
41 return scoped_ptr<V4ProtocolManager>(
42 V4ProtocolManager::Create(NULL, config));
43 }
44
45 std::string GetStockV4HashResponse() {
46 FindFullHashesResponse res;
47 res.mutable_negative_cache_duration()->set_seconds(600);
48 ThreatMatch* m = res.add_matches();
49 m->set_threat_type(API_ABUSE);
50 m->set_platform_type(CHROME_PLATFORM);
51 m->set_threat_entry_type(URL_EXPRESSION);
52 m->mutable_cache_duration()->set_seconds(300);
53 m->mutable_threat()->set_hash(
54 SBFullHashToString(SBFullHashForString("Everything's shiny, Cap'n.")));
55 ThreatEntryMetadata::MetadataEntry* e =
56 m->mutable_threat_entry_metadata()->add_entries();
57 e->set_key("permission");
58 e->set_value("NOTIFICATIONS");
59
60 // Serialize.
61 std::string res_data;
62 res.SerializeToString(&res_data);
63
64 return res_data;
65 }
66 };
67
68 void ValidateGetV4HashResults(
69 const std::vector<SBFullHashResult>& expected_full_hashes,
70 const base::TimeDelta& expected_cache_duration,
71 const std::vector<SBFullHashResult>& full_hashes,
72 const base::TimeDelta& cache_duration) {
73 EXPECT_EQ(expected_cache_duration, cache_duration);
74 ASSERT_EQ(expected_full_hashes.size(), full_hashes.size());
75
76 for (unsigned int i = 0; i < expected_full_hashes.size(); ++i) {
77 const SBFullHashResult& expected = expected_full_hashes[i];
78 const SBFullHashResult& actual = full_hashes[i];
79 EXPECT_TRUE(SBFullHashEqual(expected.hash, actual.hash));
80 EXPECT_EQ(expected.metadata, actual.metadata);
81 EXPECT_EQ(expected.cache_duration, actual.cache_duration);
82 }
83 }
84
85 TEST_F(SafeBrowsingV4ProtocolManagerTest, TestGetHashErrorHandlingNetwork) {
86 net::TestURLFetcherFactory factory;
87 scoped_ptr<V4ProtocolManager> pm(CreateProtocolManager());
88
89 std::vector<SBPrefix> prefixes;
90 std::vector<SBFullHashResult> expected_full_hashes;
91 base::TimeDelta expected_cache_duration;
92
93 pm->GetFullHashesWithApis(
94 prefixes, base::Bind(&ValidateGetV4HashResults, expected_full_hashes,
95 expected_cache_duration));
96
97 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
98 DCHECK(fetcher);
99 // Failed request status should result in error.
100 fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED,
101 net::ERR_CONNECTION_RESET));
102 fetcher->set_response_code(200);
103 fetcher->SetResponseString(GetStockV4HashResponse());
104 fetcher->delegate()->OnURLFetchComplete(fetcher);
105
106 // Should have recorded one error, but back off multiplier is unchanged.
107 EXPECT_EQ(1ul, pm->gethash_error_count_);
108 EXPECT_EQ(1ul, pm->gethash_back_off_mult_);
109 }
110
111 TEST_F(SafeBrowsingV4ProtocolManagerTest,
112 TestGetHashErrorHandlingResponseCode) {
113 net::TestURLFetcherFactory factory;
114 scoped_ptr<V4ProtocolManager> pm(CreateProtocolManager());
115
116 std::vector<SBPrefix> prefixes;
117 std::vector<SBFullHashResult> expected_full_hashes;
118 base::TimeDelta expected_cache_duration;
119
120 pm->GetFullHashesWithApis(
121 prefixes, base::Bind(&ValidateGetV4HashResults, expected_full_hashes,
122 expected_cache_duration));
123
124 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
125 DCHECK(fetcher);
126 fetcher->set_status(net::URLRequestStatus());
127 // Response code of anything other than 200 should result in error.
128 fetcher->set_response_code(204);
129 fetcher->SetResponseString(GetStockV4HashResponse());
130 fetcher->delegate()->OnURLFetchComplete(fetcher);
131
132 // Should have recorded one error, but back off multiplier is unchanged.
133 EXPECT_EQ(1ul, pm->gethash_error_count_);
134 EXPECT_EQ(1ul, pm->gethash_back_off_mult_);
135 }
136
137 TEST_F(SafeBrowsingV4ProtocolManagerTest, TestGetHashErrorHandlingOK) {
138 net::TestURLFetcherFactory factory;
139 scoped_ptr<V4ProtocolManager> pm(CreateProtocolManager());
140
141 std::vector<SBPrefix> prefixes;
142 std::vector<SBFullHashResult> expected_full_hashes;
143 SBFullHashResult hash_result;
144 hash_result.hash = SBFullHashForString("Everything's shiny, Cap'n.");
145 hash_result.metadata = "NOTIFICATIONS,";
146 hash_result.cache_duration = base::TimeDelta::FromSeconds(300);
147 expected_full_hashes.push_back(hash_result);
148 base::TimeDelta expected_cache_duration = base::TimeDelta::FromSeconds(600);
149
150 pm->GetFullHashesWithApis(
151 prefixes, base::Bind(&ValidateGetV4HashResults, expected_full_hashes,
152 expected_cache_duration));
153
154 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
155 DCHECK(fetcher);
156 fetcher->set_status(net::URLRequestStatus());
157 fetcher->set_response_code(200);
158 fetcher->SetResponseString(GetStockV4HashResponse());
159 fetcher->delegate()->OnURLFetchComplete(fetcher);
160
161 // No error, back off multiplier is unchanged.
162 EXPECT_EQ(0ul, pm->gethash_error_count_);
163 EXPECT_EQ(1ul, pm->gethash_back_off_mult_);
164 }
165
166 TEST_F(SafeBrowsingV4ProtocolManagerTest, TestGetHashBackOffTimes) {
167 scoped_ptr<V4ProtocolManager> pm(CreateProtocolManager());
168
169 // No errors or back off time yet.
170 EXPECT_EQ(0U, pm->gethash_error_count_);
171 EXPECT_EQ(1U, pm->gethash_back_off_mult_);
172 Time now = Time::Now();
173 EXPECT_TRUE(pm->next_gethash_time_ < now);
174
175 // 1 error.
176 pm->HandleGetHashError(now);
177 EXPECT_EQ(1U, pm->gethash_error_count_);
178 EXPECT_EQ(1U, pm->gethash_back_off_mult_);
179 EXPECT_LE(now + TimeDelta::FromMinutes(15), pm->next_gethash_time_);
180 EXPECT_GE(now + TimeDelta::FromMinutes(30), pm->next_gethash_time_);
181
182 // 2 errors.
183 pm->HandleGetHashError(now);
184 EXPECT_EQ(2U, pm->gethash_error_count_);
185 EXPECT_EQ(2U, pm->gethash_back_off_mult_);
186 EXPECT_LE(now + TimeDelta::FromMinutes(30), pm->next_gethash_time_);
187 EXPECT_GE(now + TimeDelta::FromMinutes(60), pm->next_gethash_time_);
188
189 // 3 errors.
190 pm->HandleGetHashError(now);
191 EXPECT_EQ(3U, pm->gethash_error_count_);
192 EXPECT_EQ(4U, pm->gethash_back_off_mult_);
193 EXPECT_LE(now + TimeDelta::FromMinutes(60), pm->next_gethash_time_);
194 EXPECT_GE(now + TimeDelta::FromMinutes(120), pm->next_gethash_time_);
195
196 // 4 errors.
197 pm->HandleGetHashError(now);
198 EXPECT_EQ(4U, pm->gethash_error_count_);
199 EXPECT_EQ(8U, pm->gethash_back_off_mult_);
200 EXPECT_LE(now + TimeDelta::FromMinutes(120), pm->next_gethash_time_);
201 EXPECT_GE(now + TimeDelta::FromMinutes(240), pm->next_gethash_time_);
202
203 // 5 errors.
204 pm->HandleGetHashError(now);
205 EXPECT_EQ(5U, pm->gethash_error_count_);
206 EXPECT_EQ(16U, pm->gethash_back_off_mult_);
207 EXPECT_LE(now + TimeDelta::FromMinutes(240), pm->next_gethash_time_);
208 EXPECT_GE(now + TimeDelta::FromMinutes(480), pm->next_gethash_time_);
209
210 // 6 errors.
211 pm->HandleGetHashError(now);
212 EXPECT_EQ(6U, pm->gethash_error_count_);
213 EXPECT_EQ(32U, pm->gethash_back_off_mult_);
214 EXPECT_LE(now + TimeDelta::FromMinutes(480), pm->next_gethash_time_);
215 EXPECT_GE(now + TimeDelta::FromMinutes(960), pm->next_gethash_time_);
216
217 // 7 errors.
218 pm->HandleGetHashError(now);
219 EXPECT_EQ(7U, pm->gethash_error_count_);
220 EXPECT_EQ(64U, pm->gethash_back_off_mult_);
221 EXPECT_LE(now + TimeDelta::FromMinutes(960), pm->next_gethash_time_);
222 EXPECT_GE(now + TimeDelta::FromMinutes(1920), pm->next_gethash_time_);
223
224 // 8 errors, reached max backoff.
225 pm->HandleGetHashError(now);
226 EXPECT_EQ(8U, pm->gethash_error_count_);
227 EXPECT_EQ(128U, pm->gethash_back_off_mult_);
228 EXPECT_EQ(now + TimeDelta::FromHours(24), pm->next_gethash_time_);
229
230 // 9 errors, reached max backoff and multiplier capped.
231 pm->HandleGetHashError(now);
232 EXPECT_EQ(9U, pm->gethash_error_count_);
233 EXPECT_EQ(128U, pm->gethash_back_off_mult_);
234 EXPECT_EQ(now + TimeDelta::FromHours(24), pm->next_gethash_time_);
235 }
236
237 TEST_F(SafeBrowsingV4ProtocolManagerTest, TestGetHashUrl) {
238 scoped_ptr<V4ProtocolManager> pm(CreateProtocolManager());
239
240 EXPECT_EQ(
241 "https://safebrowsing.googleapis.com/v4/encodedFullHashes/request_base64?"
242 "alt=proto&client_id=unittest&client_version=1.0&key=test_key_param",
243 pm->GetHashUrl("request_base64").spec());
244 }
245
246 TEST_F(SafeBrowsingV4ProtocolManagerTest, TestGetHashRequest) {
247 scoped_ptr<V4ProtocolManager> pm(CreateProtocolManager());
248
249 FindFullHashesRequest req;
250 ThreatInfo* info = req.mutable_threat_info();
251 info->add_threat_types(API_ABUSE);
252 info->add_platform_types(CHROME_PLATFORM);
253 info->add_threat_entry_types(URL_EXPRESSION);
254
255 SBPrefix one = 1u;
256 SBPrefix two = 2u;
257 SBPrefix three = 3u;
258 std::string hash(reinterpret_cast<const char*>(&one), sizeof(SBPrefix));
259 info->add_threat_entries()->set_hash(hash);
260 hash.clear();
261 hash.append(reinterpret_cast<const char*>(&two), sizeof(SBPrefix));
262 info->add_threat_entries()->set_hash(hash);
263 hash.clear();
264 hash.append(reinterpret_cast<const char*>(&three), sizeof(SBPrefix));
265 info->add_threat_entries()->set_hash(hash);
266
267 // Serialize and Base64 encode.
268 std::string req_data, req_base64;
269 req.SerializeToString(&req_data);
270 base::Base64Encode(req_data, &req_base64);
271
272 std::vector<PlatformType> platform;
273 platform.push_back(CHROME_PLATFORM);
274 std::vector<SBPrefix> prefixes;
275 prefixes.push_back(one);
276 prefixes.push_back(two);
277 prefixes.push_back(three);
278 EXPECT_EQ(req_base64, pm->GetHashRequest(prefixes, platform, API_ABUSE));
279 }
280
281 TEST_F(SafeBrowsingV4ProtocolManagerTest, TestParseHashResponse) {
282 scoped_ptr<V4ProtocolManager> pm(CreateProtocolManager());
283
284 FindFullHashesResponse res;
285 res.mutable_negative_cache_duration()->set_seconds(600);
286 res.mutable_minimum_wait_duration()->set_seconds(400);
287 ThreatMatch* m = res.add_matches();
288 m->set_threat_type(API_ABUSE);
289 m->set_platform_type(CHROME_PLATFORM);
290 m->set_threat_entry_type(URL_EXPRESSION);
291 m->mutable_cache_duration()->set_seconds(300);
292 m->mutable_threat()->set_hash(
293 SBFullHashToString(SBFullHashForString("Everything's shiny, Cap'n.")));
294 ThreatEntryMetadata::MetadataEntry* e =
295 m->mutable_threat_entry_metadata()->add_entries();
296 e->set_key("permission");
297 e->set_value("NOTIFICATIONS");
298
299 // Serialize.
300 std::string res_data;
301 res.SerializeToString(&res_data);
302
303 Time now = Time::Now();
304 std::vector<SBFullHashResult> full_hashes;
305 base::TimeDelta cache_lifetime;
306 EXPECT_TRUE(pm->ParseHashResponse(res_data, &full_hashes, &cache_lifetime));
307
308 EXPECT_EQ(base::TimeDelta::FromSeconds(600), cache_lifetime);
309 EXPECT_EQ(1ul, full_hashes.size());
310 EXPECT_TRUE(SBFullHashEqual(SBFullHashForString("Everything's shiny, Cap'n."),
311 full_hashes[0].hash));
312 EXPECT_EQ("NOTIFICATIONS,", full_hashes[0].metadata);
313 EXPECT_EQ(base::TimeDelta::FromSeconds(300), full_hashes[0].cache_duration);
314 EXPECT_LE(now + base::TimeDelta::FromSeconds(400), pm->next_gethash_time_);
315 }
316
317 // Adds an entry with an ignored ThreatEntryType.
318 TEST_F(SafeBrowsingV4ProtocolManagerTest,
319 TestParseHashResponseWrongThreatEntryType) {
320 scoped_ptr<V4ProtocolManager> pm(CreateProtocolManager());
321
322 FindFullHashesResponse res;
323 res.mutable_negative_cache_duration()->set_seconds(600);
324 res.add_matches()->set_threat_entry_type(BINARY_DIGEST);
325
326 // Serialize.
327 std::string res_data;
328 res.SerializeToString(&res_data);
329
330 std::vector<SBFullHashResult> full_hashes;
331 base::TimeDelta cache_lifetime;
332 EXPECT_FALSE(pm->ParseHashResponse(res_data, &full_hashes, &cache_lifetime));
333
334 EXPECT_EQ(base::TimeDelta::FromSeconds(600), cache_lifetime);
335 // There should be no hash results.
336 EXPECT_EQ(0ul, full_hashes.size());
337 }
338
339 // Adds an entry with a SOCIAL_ENGINEERING threat type.
340 TEST_F(SafeBrowsingV4ProtocolManagerTest,
341 TestParseHashResponseSocialEngineeringThreatType) {
342 scoped_ptr<V4ProtocolManager> pm(CreateProtocolManager());
343
344 FindFullHashesResponse res;
345 res.mutable_negative_cache_duration()->set_seconds(600);
346 ThreatMatch* m = res.add_matches();
347 m->set_threat_type(SOCIAL_ENGINEERING);
348 m->set_platform_type(CHROME_PLATFORM);
349 m->set_threat_entry_type(URL_EXPRESSION);
350 m->mutable_threat()->set_hash(
351 SBFullHashToString(SBFullHashForString("Not to fret.")));
352 ThreatEntryMetadata::MetadataEntry* e =
353 m->mutable_threat_entry_metadata()->add_entries();
354 e->set_key("permission");
355 e->set_value("IGNORED");
356
357 // Serialize.
358 std::string res_data;
359 res.SerializeToString(&res_data);
360
361 std::vector<SBFullHashResult> full_hashes;
362 base::TimeDelta cache_lifetime;
363 EXPECT_FALSE(pm->ParseHashResponse(res_data, &full_hashes, &cache_lifetime));
364
365 EXPECT_EQ(base::TimeDelta::FromSeconds(600), cache_lifetime);
366 EXPECT_EQ(0ul, full_hashes.size());
367 }
368
369 // Adds metadata with a key value that is not "permission".
370 TEST_F(SafeBrowsingV4ProtocolManagerTest,
371 TestParseHashResponseNonPermissionMetadata) {
372 scoped_ptr<V4ProtocolManager> pm(CreateProtocolManager());
373
374 FindFullHashesResponse res;
375 res.mutable_negative_cache_duration()->set_seconds(600);
376 ThreatMatch* m = res.add_matches();
377 m->set_threat_type(API_ABUSE);
378 m->set_platform_type(CHROME_PLATFORM);
379 m->set_threat_entry_type(URL_EXPRESSION);
380 m->mutable_threat()->set_hash(
381 SBFullHashToString(SBFullHashForString("Not to fret.")));
382 ThreatEntryMetadata::MetadataEntry* e =
383 m->mutable_threat_entry_metadata()->add_entries();
384 e->set_key("notpermission");
385 e->set_value("NOTGEOLOCATION");
386
387 // Serialize.
388 std::string res_data;
389 res.SerializeToString(&res_data);
390
391 std::vector<SBFullHashResult> full_hashes;
392 base::TimeDelta cache_lifetime;
393 EXPECT_TRUE(pm->ParseHashResponse(res_data, &full_hashes, &cache_lifetime));
394
395 EXPECT_EQ(base::TimeDelta::FromSeconds(600), cache_lifetime);
396 EXPECT_EQ(1ul, full_hashes.size());
397
398 EXPECT_TRUE(SBFullHashEqual(SBFullHashForString("Not to fret."),
399 full_hashes[0].hash));
400 // Metadata should be empty.
401 EXPECT_EQ("", full_hashes[0].metadata);
402 EXPECT_EQ(base::TimeDelta::FromSeconds(0), full_hashes[0].cache_duration);
403 }
404
405 TEST_F(SafeBrowsingV4ProtocolManagerTest,
406 TestParseHashResponseInconsistentThreatTypes) {
407 scoped_ptr<V4ProtocolManager> pm(CreateProtocolManager());
408
409 FindFullHashesResponse res;
410 ThreatMatch* m1 = res.add_matches();
411 m1->set_threat_type(API_ABUSE);
412 m1->set_platform_type(CHROME_PLATFORM);
413 m1->set_threat_entry_type(URL_EXPRESSION);
414 m1->mutable_threat()->set_hash(
415 SBFullHashToString(SBFullHashForString("Everything's shiny, Cap'n.")));
416 m1->mutable_threat_entry_metadata()->add_entries();
417 ThreatMatch* m2 = res.add_matches();
418 m2->set_threat_type(MALWARE_THREAT);
419 m2->set_threat_entry_type(URL_EXPRESSION);
420 m2->mutable_threat()->set_hash(
421 SBFullHashToString(SBFullHashForString("Not to fret.")));
422
423 // Serialize.
424 std::string res_data;
425 res.SerializeToString(&res_data);
426
427 std::vector<SBFullHashResult> full_hashes;
428 base::TimeDelta cache_lifetime;
429 EXPECT_FALSE(pm->ParseHashResponse(res_data, &full_hashes, &cache_lifetime));
430 }
431
432 } // namespace safe_browsing
OLDNEW
« no previous file with comments | « chrome/browser/safe_browsing/v4_protocol_manager.cc ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698