1 // Copyright (c) 2012 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 <algorithm> 6 7 #include "base/bind.h" 8 #include "base/pickle.h" 9 #include "base/run_loop.h" 10 #include "base/time/time.h" 11 #include "chrome/browser/history/history_backend.h" 12 #include "chrome/browser/history/history_service.h" 13 #include "chrome/browser/history/history_service_factory.h" 14 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/safe_browsing/malware_details.h" 16 #include "chrome/browser/safe_browsing/malware_details_history.h" 17 #include "chrome/browser/safe_browsing/report.pb.h" 18 #include "chrome/browser/safe_browsing/safe_browsing_service.h" 19 #include "chrome/browser/safe_browsing/ui_manager.h" 20 #include "chrome/common/render_messages.h" 21 #include "chrome/common/safe_browsing/safebrowsing_messages.h" 22 #include "chrome/test/base/chrome_render_view_host_test_harness.h" 23 #include "chrome/test/base/testing_profile.h" 24 #include "content/public/browser/render_process_host.h" 25 #include "content/public/browser/web_contents.h" 26 #include "net/base/io_buffer.h" 27 #include "net/base/net_errors.h" 28 #include "net/base/test_completion_callback.h" 29 #include "net/disk_cache/disk_cache.h" 30 #include "net/http/http_cache.h" 31 #include "net/http/http_response_headers.h" 32 #include "net/http/http_response_info.h" 33 #include "net/http/http_util.h" 34 #include "net/url_request/url_request_context.h" 35 #include "net/url_request/url_request_context_getter.h" 36 37 static const char* kOriginalLandingURL = "http://www.originallandingpage.com/"; 38 static const char* kHttpsURL = "https://www.url.com/"; 39 static const char* kDOMChildURL = "http://www.domparent.com/"; 40 static const char* kDOMParentURL = "http://www.domchild.com/"; 41 static const char* kFirstRedirectURL = "http://redirectone.com/"; 42 static const char* kSecondRedirectURL = "http://redirecttwo.com/"; 43 44 static const char* kMalwareURL = "http://www.malware.com/"; 45 static const char* kMalwareHeaders = 46 "HTTP/1.1 200 OK\n" 47 "Content-Type: image/jpeg\n"; 48 static const char* kMalwareData = "exploit();"; 49 50 static const char* kLandingURL = "http://www.landingpage.com/"; 51 static const char* kLandingHeaders = 52 "HTTP/1.1 200 OK\n" 53 "Content-Type: text/html\n" 54 "Content-Length: 1024\n" 55 "Set-Cookie: tastycookie\n"; // This header is stripped. 56 static const char* kLandingData = "<iframe src='http://www.malware.com'>"; 57 58 using content::BrowserThread; 59 using content::WebContents; 60 using safe_browsing::ClientMalwareReportRequest; 61 62 namespace { 63 64 void WriteHeaders(disk_cache::Entry* entry, const std::string& headers) { 65 net::HttpResponseInfo responseinfo; 66 std::string raw_headers = net::HttpUtil::AssembleRawHeaders( 67 headers.c_str(), headers.size()); 68 responseinfo.socket_address = net::HostPortPair("1.2.3.4", 80); 69 responseinfo.headers = new net::HttpResponseHeaders(raw_headers); 70 71 Pickle pickle; 72 responseinfo.Persist(&pickle, false, false); 73 74 scoped_refptr<net::WrappedIOBuffer> buf(new net::WrappedIOBuffer( 75 reinterpret_cast<const char*>(pickle.data()))); 76 int len = static_cast<int>(pickle.size()); 77 78 net::TestCompletionCallback cb; 79 int rv = entry->WriteData(0, 0, buf.get(), len, cb.callback(), true); 80 ASSERT_EQ(len, cb.GetResult(rv)); 81 } 82 83 void WriteData(disk_cache::Entry* entry, const std::string& data) { 84 if (data.empty()) 85 return; 86 87 int len = data.length(); 88 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(len)); 89 memcpy(buf->data(), data.data(), data.length()); 90 91 net::TestCompletionCallback cb; 92 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true); 93 ASSERT_EQ(len, cb.GetResult(rv)); 94 } 95 96 void WriteToEntry(disk_cache::Backend* cache, const std::string& key, 97 const std::string& headers, const std::string& data) { 98 net::TestCompletionCallback cb; 99 disk_cache::Entry* entry; 100 int rv = cache->CreateEntry(key, &entry, cb.callback()); 101 rv = cb.GetResult(rv); 102 if (rv != net::OK) { 103 rv = cache->OpenEntry(key, &entry, cb.callback()); 104 ASSERT_EQ(net::OK, cb.GetResult(rv)); 105 } 106 107 WriteHeaders(entry, headers); 108 WriteData(entry, data); 109 entry->Close(); 110 } 111 112 void FillCache(net::URLRequestContextGetter* context_getter) { 113 net::TestCompletionCallback cb; 114 disk_cache::Backend* cache; 115 int rv = 116 context_getter->GetURLRequestContext()->http_transaction_factory()-> 117 GetCache()->GetBackend(&cache, cb.callback()); 118 ASSERT_EQ(net::OK, cb.GetResult(rv)); 119 120 WriteToEntry(cache, kMalwareURL, kMalwareHeaders, kMalwareData); 121 WriteToEntry(cache, kLandingURL, kLandingHeaders, kLandingData); 122 } 123 124 // Lets us provide a MockURLRequestContext with an HTTP Cache we pre-populate. 125 // Also exposes the constructor. 126 class MalwareDetailsWrap : public MalwareDetails { 127 public: 128 MalwareDetailsWrap( 129 SafeBrowsingUIManager* ui_manager, 130 WebContents* web_contents, 131 const SafeBrowsingUIManager::UnsafeResource& unsafe_resource, 132 net::URLRequestContextGetter* request_context_getter) 133 : MalwareDetails(ui_manager, web_contents, unsafe_resource) { 134 135 request_context_getter_ = request_context_getter; 136 } 137 138 private: 139 virtual ~MalwareDetailsWrap() {} 140 }; 141 142 class MockSafeBrowsingUIManager : public SafeBrowsingUIManager { 143 public: 144 base::RunLoop* run_loop_; 145 // The safe browsing UI manager does not need a service for this test. 146 MockSafeBrowsingUIManager() 147 : SafeBrowsingUIManager(NULL), run_loop_(NULL) {} 148 149 // When the MalwareDetails is done, this is called. 150 virtual void SendSerializedMalwareDetails( 151 const std::string& serialized) OVERRIDE { 152 DVLOG(1) << "SendSerializedMalwareDetails"; 153 run_loop_->Quit(); 154 run_loop_ = NULL; 155 serialized_ = serialized; 156 } 157 158 // Used to synchronize SendSerializedMalwareDetails() with 159 // WaitForSerializedReport(). RunLoop::RunUntilIdle() is not sufficient 160 // because the MessageLoop task queue completely drains at some point 161 // between the send and the wait. 162 void SetRunLoopToQuit(base::RunLoop* run_loop) { 163 DCHECK(run_loop_ == NULL); 164 run_loop_ = run_loop; 165 } 166 167 const std::string& GetSerialized() { 168 return serialized_; 169 } 170 171 private: 172 virtual ~MockSafeBrowsingUIManager() {} 173 174 std::string serialized_; 175 DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingUIManager); 176 }; 177 178 } // namespace. 179 180 class MalwareDetailsTest : public ChromeRenderViewHostTestHarness { 181 public: 182 typedef SafeBrowsingUIManager::UnsafeResource UnsafeResource; 183 184 MalwareDetailsTest() 185 : ui_manager_(new MockSafeBrowsingUIManager()) { 186 } 187 188 virtual void SetUp() OVERRIDE { 189 ChromeRenderViewHostTestHarness::SetUp(); 190 ASSERT_TRUE(profile()->CreateHistoryService( 191 true /* delete_file */, false /* no_db */)); 192 } 193 194 virtual void TearDown() OVERRIDE { 195 profile()->DestroyHistoryService(); 196 ChromeRenderViewHostTestHarness::TearDown(); 197 } 198 199 static bool ResourceLessThan( 200 const ClientMalwareReportRequest::Resource* lhs, 201 const ClientMalwareReportRequest::Resource* rhs) { 202 return lhs->id() < rhs->id(); 203 } 204 205 std::string WaitForSerializedReport(MalwareDetails* report) { 206 BrowserThread::PostTask( 207 BrowserThread::IO, 208 FROM_HERE, 209 base::Bind(&MalwareDetails::FinishCollection, report)); 210 // Wait for the callback (SendSerializedMalwareDetails). 211 DVLOG(1) << "Waiting for SendSerializedMalwareDetails"; 212 base::RunLoop run_loop; 213 ui_manager_->SetRunLoopToQuit(&run_loop); 214 run_loop.Run(); 215 return ui_manager_->GetSerialized(); 216 } 217 218 HistoryService* history_service() { 219 return HistoryServiceFactory::GetForProfile(profile(), 220 Profile::EXPLICIT_ACCESS); 221 } 222 223 protected: 224 void InitResource(UnsafeResource* resource, 225 bool is_subresource, 226 const GURL& url) { 227 resource->url = url; 228 resource->is_subresource = is_subresource; 229 resource->threat_type = SB_THREAT_TYPE_URL_MALWARE; 230 resource->render_process_host_id = 231 web_contents()->GetRenderProcessHost()->GetID(); 232 resource->render_view_id = 233 web_contents()->GetRenderViewHost()->GetRoutingID(); 234 } 235 236 void VerifyResults(const ClientMalwareReportRequest& report_pb, 237 const ClientMalwareReportRequest& expected_pb) { 238 EXPECT_EQ(expected_pb.malware_url(), report_pb.malware_url()); 239 EXPECT_EQ(expected_pb.page_url(), report_pb.page_url()); 240 EXPECT_EQ(expected_pb.referrer_url(), report_pb.referrer_url()); 241 242 ASSERT_EQ(expected_pb.resources_size(), report_pb.resources_size()); 243 // Sort the resources, to make the test deterministic 244 std::vector<const ClientMalwareReportRequest::Resource*> resources; 245 for (int i = 0; i < report_pb.resources_size(); ++i) { 246 const ClientMalwareReportRequest::Resource& resource = 247 report_pb.resources(i); 248 resources.push_back(&resource); 249 } 250 std::sort(resources.begin(), resources.end(), 251 &MalwareDetailsTest::ResourceLessThan); 252 253 std::vector<const ClientMalwareReportRequest::Resource*> expected; 254 for (int i = 0; i < report_pb.resources_size(); ++i) { 255 const ClientMalwareReportRequest::Resource& resource = 256 expected_pb.resources(i); 257 expected.push_back(&resource); 258 } 259 std::sort(expected.begin(), expected.end(), 260 &MalwareDetailsTest::ResourceLessThan); 261 262 for (uint32 i = 0; i < expected.size(); ++i) { 263 VerifyResource(resources[i], expected[i]); 264 } 265 266 EXPECT_EQ(expected_pb.complete(), report_pb.complete()); 267 } 268 269 void VerifyResource(const ClientMalwareReportRequest::Resource* resource, 270 const ClientMalwareReportRequest::Resource* expected) { 271 EXPECT_EQ(expected->id(), resource->id()); 272 EXPECT_EQ(expected->url(), resource->url()); 273 EXPECT_EQ(expected->parent_id(), resource->parent_id()); 274 ASSERT_EQ(expected->child_ids_size(), resource->child_ids_size()); 275 for (int i = 0; i < expected->child_ids_size(); i++) { 276 EXPECT_EQ(expected->child_ids(i), resource->child_ids(i)); 277 } 278 279 // Verify HTTP Responses 280 if (expected->has_response()) { 281 ASSERT_TRUE(resource->has_response()); 282 EXPECT_EQ(expected->response().firstline().code(), 283 resource->response().firstline().code()); 284 285 ASSERT_EQ(expected->response().headers_size(), 286 resource->response().headers_size()); 287 for (int i = 0; i < expected->response().headers_size(); ++i) { 288 EXPECT_EQ(expected->response().headers(i).name(), 289 resource->response().headers(i).name()); 290 EXPECT_EQ(expected->response().headers(i).value(), 291 resource->response().headers(i).value()); 292 } 293 294 EXPECT_EQ(expected->response().body(), resource->response().body()); 295 EXPECT_EQ(expected->response().bodylength(), 296 resource->response().bodylength()); 297 EXPECT_EQ(expected->response().bodydigest(), 298 resource->response().bodydigest()); 299 } 300 301 // Verify IP:port pair 302 EXPECT_EQ(expected->response().remote_ip(), 303 resource->response().remote_ip()); 304 } 305 306 // Adds a page to history. 307 // The redirects is the redirect url chain leading to the url. 308 void AddPageToHistory(const GURL& url, 309 history::RedirectList* redirects) { 310 // The last item of the redirect chain has to be the final url when adding 311 // to history backend. 312 redirects->push_back(url); 313 history_service()->AddPage( 314 url, base::Time::Now(), static_cast<void*>(this), 0, GURL(), 315 *redirects, content::PAGE_TRANSITION_TYPED, history::SOURCE_BROWSED, 316 false); 317 } 318 319 scoped_refptr<MockSafeBrowsingUIManager> ui_manager_; 320 }; 321 322 // Tests creating a simple malware report. 323 TEST_F(MalwareDetailsTest, MalwareSubResource) { 324 // Start a load. 325 controller().LoadURL(GURL(kLandingURL), content::Referrer(), 326 content::PAGE_TRANSITION_TYPED, std::string()); 327 328 UnsafeResource resource; 329 InitResource(&resource, true, GURL(kMalwareURL)); 330 331 scoped_refptr<MalwareDetailsWrap> report = 332 new MalwareDetailsWrap(ui_manager_.get(), web_contents(), resource, NULL); 333 334 std::string serialized = WaitForSerializedReport(report.get()); 335 336 ClientMalwareReportRequest actual; 337 actual.ParseFromString(serialized); 338 339 ClientMalwareReportRequest expected; 340 expected.set_malware_url(kMalwareURL); 341 expected.set_page_url(kLandingURL); 342 expected.set_referrer_url(""); 343 344 ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources(); 345 pb_resource->set_id(0); 346 pb_resource->set_url(kLandingURL); 347 pb_resource = expected.add_resources(); 348 pb_resource->set_id(1); 349 pb_resource->set_url(kMalwareURL); 350 351 VerifyResults(actual, expected); 352 } 353 354 // Tests creating a simple malware report where the subresource has a 355 // different original_url. 356 TEST_F(MalwareDetailsTest, MalwareSubResourceWithOriginalUrl) { 357 controller().LoadURL(GURL(kLandingURL), content::Referrer(), 358 content::PAGE_TRANSITION_TYPED, std::string()); 359 360 UnsafeResource resource; 361 InitResource(&resource, true, GURL(kMalwareURL)); 362 resource.original_url = GURL(kOriginalLandingURL); 363 364 scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap( 365 ui_manager_.get(), web_contents(), resource, NULL); 366 367 std::string serialized = WaitForSerializedReport(report.get()); 368 369 ClientMalwareReportRequest actual; 370 actual.ParseFromString(serialized); 371 372 ClientMalwareReportRequest expected; 373 expected.set_malware_url(kMalwareURL); 374 expected.set_page_url(kLandingURL); 375 expected.set_referrer_url(""); 376 377 ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources(); 378 pb_resource->set_id(0); 379 pb_resource->set_url(kLandingURL); 380 381 pb_resource = expected.add_resources(); 382 pb_resource->set_id(1); 383 pb_resource->set_url(kOriginalLandingURL); 384 385 pb_resource = expected.add_resources(); 386 pb_resource->set_id(2); 387 pb_resource->set_url(kMalwareURL); 388 // The Resource for kMmalwareUrl should have the Resource for 389 // kOriginalLandingURL (with id 1) as parent. 390 pb_resource->set_parent_id(1); 391 392 VerifyResults(actual, expected); 393 } 394 395 // Tests creating a malware report with data from the renderer. 396 TEST_F(MalwareDetailsTest, MalwareDOMDetails) { 397 controller().LoadURL(GURL(kLandingURL), content::Referrer(), 398 content::PAGE_TRANSITION_TYPED, std::string()); 399 400 UnsafeResource resource; 401 InitResource(&resource, true, GURL(kMalwareURL)); 402 403 scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap( 404 ui_manager_.get(), web_contents(), resource, NULL); 405 406 // Send a message from the DOM, with 2 nodes, a parent and a child. 407 std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node> params; 408 SafeBrowsingHostMsg_MalwareDOMDetails_Node child_node; 409 child_node.url = GURL(kDOMChildURL); 410 child_node.tag_name = "iframe"; 411 child_node.parent = GURL(kDOMParentURL); 412 params.push_back(child_node); 413 SafeBrowsingHostMsg_MalwareDOMDetails_Node parent_node; 414 parent_node.url = GURL(kDOMParentURL); 415 parent_node.children.push_back(GURL(kDOMChildURL)); 416 params.push_back(parent_node); 417 report->OnReceivedMalwareDOMDetails(params); 418 419 std::string serialized = WaitForSerializedReport(report.get()); 420 ClientMalwareReportRequest actual; 421 actual.ParseFromString(serialized); 422 423 ClientMalwareReportRequest expected; 424 expected.set_malware_url(kMalwareURL); 425 expected.set_page_url(kLandingURL); 426 expected.set_referrer_url(""); 427 428 ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources(); 429 pb_resource->set_id(0); 430 pb_resource->set_url(kLandingURL); 431 432 pb_resource = expected.add_resources(); 433 pb_resource->set_id(1); 434 pb_resource->set_url(kMalwareURL); 435 436 pb_resource = expected.add_resources(); 437 pb_resource->set_id(2); 438 pb_resource->set_url(kDOMChildURL); 439 pb_resource->set_parent_id(3); 440 441 pb_resource = expected.add_resources(); 442 pb_resource->set_id(3); 443 pb_resource->set_url(kDOMParentURL); 444 pb_resource->add_child_ids(2); 445 expected.set_complete(false); // Since the cache was missing. 446 447 VerifyResults(actual, expected); 448 } 449 450 // Verify that https:// urls are dropped. 451 TEST_F(MalwareDetailsTest, NotPublicUrl) { 452 controller().LoadURL(GURL(kHttpsURL), content::Referrer(), 453 content::PAGE_TRANSITION_TYPED, std::string()); 454 UnsafeResource resource; 455 InitResource(&resource, true, GURL(kMalwareURL)); 456 scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap( 457 ui_manager_.get(), web_contents(), resource, NULL); 458 459 std::string serialized = WaitForSerializedReport(report.get()); 460 ClientMalwareReportRequest actual; 461 actual.ParseFromString(serialized); 462 463 ClientMalwareReportRequest expected; 464 expected.set_malware_url(kMalwareURL); // No page_url 465 expected.set_referrer_url(""); 466 467 ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources(); 468 pb_resource->set_url(kMalwareURL); // Only one resource 469 470 VerifyResults(actual, expected); 471 } 472 473 // Tests creating a malware report where there are redirect urls to an unsafe 474 // resource url 475 TEST_F(MalwareDetailsTest, MalwareWithRedirectUrl) { 476 controller().LoadURL(GURL(kLandingURL), content::Referrer(), 477 content::PAGE_TRANSITION_TYPED, std::string()); 478 479 UnsafeResource resource; 480 InitResource(&resource, true, GURL(kMalwareURL)); 481 resource.original_url = GURL(kOriginalLandingURL); 482 483 // add some redirect urls 484 resource.redirect_urls.push_back(GURL(kFirstRedirectURL)); 485 resource.redirect_urls.push_back(GURL(kSecondRedirectURL)); 486 resource.redirect_urls.push_back(GURL(kMalwareURL)); 487 488 scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap( 489 ui_manager_.get(), web_contents(), resource, NULL); 490 491 std::string serialized = WaitForSerializedReport(report.get()); 492 ClientMalwareReportRequest actual; 493 actual.ParseFromString(serialized); 494 495 ClientMalwareReportRequest expected; 496 expected.set_malware_url(kMalwareURL); 497 expected.set_page_url(kLandingURL); 498 expected.set_referrer_url(""); 499 500 ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources(); 501 pb_resource->set_id(0); 502 pb_resource->set_url(kLandingURL); 503 504 pb_resource = expected.add_resources(); 505 pb_resource->set_id(1); 506 pb_resource->set_url(kOriginalLandingURL); 507 508 pb_resource = expected.add_resources(); 509 pb_resource->set_id(2); 510 pb_resource->set_url(kMalwareURL); 511 pb_resource->set_parent_id(4); 512 513 pb_resource = expected.add_resources(); 514 pb_resource->set_id(3); 515 pb_resource->set_url(kFirstRedirectURL); 516 pb_resource->set_parent_id(1); 517 518 pb_resource = expected.add_resources(); 519 pb_resource->set_id(4); 520 pb_resource->set_url(kSecondRedirectURL); 521 pb_resource->set_parent_id(3); 522 523 VerifyResults(actual, expected); 524 } 525 526 // Tests the interaction with the HTTP cache. 527 TEST_F(MalwareDetailsTest, HTTPCache) { 528 controller().LoadURL(GURL(kLandingURL), content::Referrer(), 529 content::PAGE_TRANSITION_TYPED, std::string()); 530 531 UnsafeResource resource; 532 InitResource(&resource, true, GURL(kMalwareURL)); 533 534 scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap( 535 ui_manager_.get(), web_contents(), resource, 536 profile()->GetRequestContext()); 537 538 BrowserThread::PostTask( 539 BrowserThread::IO, FROM_HERE, 540 base::Bind(&FillCache, 541 make_scoped_refptr(profile()->GetRequestContext()))); 542 543 // The cache collection starts after the IPC from the DOM is fired. 544 std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node> params; 545 report->OnReceivedMalwareDOMDetails(params); 546 547 // Let the cache callbacks complete. 548 base::RunLoop().RunUntilIdle(); 549 550 DVLOG(1) << "Getting serialized report"; 551 std::string serialized = WaitForSerializedReport(report.get()); 552 ClientMalwareReportRequest actual; 553 actual.ParseFromString(serialized); 554 555 ClientMalwareReportRequest expected; 556 expected.set_malware_url(kMalwareURL); 557 expected.set_page_url(kLandingURL); 558 expected.set_referrer_url(""); 559 560 ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources(); 561 pb_resource->set_id(0); 562 pb_resource->set_url(kLandingURL); 563 safe_browsing::ClientMalwareReportRequest::HTTPResponse* pb_response = 564 pb_resource->mutable_response(); 565 pb_response->mutable_firstline()->set_code(200); 566 safe_browsing::ClientMalwareReportRequest::HTTPHeader* pb_header = 567 pb_response->add_headers(); 568 pb_header->set_name("Content-Type"); 569 pb_header->set_value("text/html"); 570 pb_header = pb_response->add_headers(); 571 pb_header->set_name("Content-Length"); 572 pb_header->set_value("1024"); 573 pb_header = pb_response->add_headers(); 574 pb_header->set_name("Set-Cookie"); 575 pb_header->set_value(""); // The cookie is dropped. 576 pb_response->set_body(kLandingData); 577 pb_response->set_bodylength(37); 578 pb_response->set_bodydigest("9ca97475598a79bc1e8fc9bd6c72cd35"); 579 pb_response->set_remote_ip("1.2.3.4:80"); 580 581 pb_resource = expected.add_resources(); 582 pb_resource->set_id(1); 583 pb_resource->set_url(kMalwareURL); 584 pb_response = pb_resource->mutable_response(); 585 pb_response->mutable_firstline()->set_code(200); 586 pb_header = pb_response->add_headers(); 587 pb_header->set_name("Content-Type"); 588 pb_header->set_value("image/jpeg"); 589 pb_response->set_body(kMalwareData); 590 pb_response->set_bodylength(10); 591 pb_response->set_bodydigest("581373551c43d4cf33bfb3b26838ff95"); 592 pb_response->set_remote_ip("1.2.3.4:80"); 593 expected.set_complete(true); 594 595 VerifyResults(actual, expected); 596 } 597 598 // Tests the interaction with the HTTP cache (where the cache is empty). 599 TEST_F(MalwareDetailsTest, HTTPCacheNoEntries) { 600 controller().LoadURL(GURL(kLandingURL), content::Referrer(), 601 content::PAGE_TRANSITION_TYPED, std::string()); 602 603 UnsafeResource resource; 604 InitResource(&resource, true, GURL(kMalwareURL)); 605 606 scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap( 607 ui_manager_.get(), web_contents(), resource, 608 profile()->GetRequestContext()); 609 610 // No call to FillCache 611 612 // The cache collection starts after the IPC from the DOM is fired. 613 std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node> params; 614 report->OnReceivedMalwareDOMDetails(params); 615 616 // Let the cache callbacks complete. 617 base::RunLoop().RunUntilIdle(); 618 619 DVLOG(1) << "Getting serialized report"; 620 std::string serialized = WaitForSerializedReport(report.get()); 621 ClientMalwareReportRequest actual; 622 actual.ParseFromString(serialized); 623 624 ClientMalwareReportRequest expected; 625 expected.set_malware_url(kMalwareURL); 626 expected.set_page_url(kLandingURL); 627 expected.set_referrer_url(""); 628 629 ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources(); 630 pb_resource->set_id(0); 631 pb_resource->set_url(kLandingURL); 632 pb_resource = expected.add_resources(); 633 pb_resource->set_id(1); 634 pb_resource->set_url(kMalwareURL); 635 expected.set_complete(true); 636 637 VerifyResults(actual, expected); 638 } 639 640 // Test getting redirects from history service. 641 TEST_F(MalwareDetailsTest, HistoryServiceUrls) { 642 // Add content to history service. 643 // There are two redirect urls before reacing malware url: 644 // kFirstRedirectURL -> kSecondRedirectURL -> kMalwareURL 645 GURL baseurl(kMalwareURL); 646 history::RedirectList redirects; 647 redirects.push_back(GURL(kFirstRedirectURL)); 648 redirects.push_back(GURL(kSecondRedirectURL)); 649 AddPageToHistory(baseurl, &redirects); 650 // Wait for history service operation finished. 651 profile()->BlockUntilHistoryProcessesPendingRequests(); 652 653 controller().LoadURL(GURL(kLandingURL), content::Referrer(), 654 content::PAGE_TRANSITION_TYPED, std::string()); 655 656 UnsafeResource resource; 657 InitResource(&resource, true, GURL(kMalwareURL)); 658 scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap( 659 ui_manager_.get(), web_contents(), resource, NULL); 660 661 // The redirects collection starts after the IPC from the DOM is fired. 662 std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node> params; 663 report->OnReceivedMalwareDOMDetails(params); 664 665 // Let the redirects callbacks complete. 666 base::RunLoop().RunUntilIdle(); 667 668 std::string serialized = WaitForSerializedReport(report.get()); 669 ClientMalwareReportRequest actual; 670 actual.ParseFromString(serialized); 671 672 ClientMalwareReportRequest expected; 673 expected.set_malware_url(kMalwareURL); 674 expected.set_page_url(kLandingURL); 675 expected.set_referrer_url(""); 676 677 ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources(); 678 pb_resource->set_id(0); 679 pb_resource->set_url(kLandingURL); 680 pb_resource = expected.add_resources(); 681 pb_resource->set_id(1); 682 pb_resource->set_parent_id(2); 683 pb_resource->set_url(kMalwareURL); 684 pb_resource = expected.add_resources(); 685 pb_resource->set_id(2); 686 pb_resource->set_parent_id(3); 687 pb_resource->set_url(kSecondRedirectURL); 688 pb_resource = expected.add_resources(); 689 pb_resource->set_id(3); 690 pb_resource->set_url(kFirstRedirectURL); 691 692 VerifyResults(actual, expected); 693 } 694