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