| OLD | NEW |
| (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 | |
| OLD | NEW |