Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / safe_browsing / malware_details_unittest.cc
blob83f451303019861e3dd58fb09c5f8b5e46422a60
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/render_messages.h"
19 #include "chrome/common/safe_browsing/safebrowsing_messages.h"
20 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
21 #include "chrome/test/base/testing_profile.h"
22 #include "components/history/core/browser/history_backend.h"
23 #include "components/history/core/browser/history_service.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"
37 // Mixture of HTTP and HTTPS. No special treatment for HTTPS.
38 static const char* kOriginalLandingURL =
39 "http://www.originallandingpage.com/with/path";
40 static const char* kDOMChildURL = "https://www.domparent.com/with/path";
41 static const char* kDOMParentURL = "https://www.domchild.com/with/path";
42 static const char* kFirstRedirectURL = "http://redirectone.com/with/path";
43 static const char* kSecondRedirectURL = "https://redirecttwo.com/with/path";
44 static const char* kReferrerURL = "http://www.referrer.com/with/path";
46 static const char* kMalwareURL = "http://www.malware.com/with/path";
47 static const char* kMalwareHeaders =
48 "HTTP/1.1 200 OK\n"
49 "Content-Type: image/jpeg\n";
50 static const char* kMalwareData = "exploit();";
52 static const char* kLandingURL = "http://www.landingpage.com/with/path";
53 static const char* kLandingHeaders =
54 "HTTP/1.1 200 OK\n"
55 "Content-Type: text/html\n"
56 "Content-Length: 1024\n"
57 "Set-Cookie: tastycookie\n"; // This header is stripped.
58 static const char* kLandingData =
59 "<iframe src='http://www.malware.com/with/path'>";
62 using content::BrowserThread;
63 using content::WebContents;
64 using safe_browsing::ClientMalwareReportRequest;
66 namespace {
68 void WriteHeaders(disk_cache::Entry* entry, const std::string& headers) {
69 net::HttpResponseInfo responseinfo;
70 std::string raw_headers = net::HttpUtil::AssembleRawHeaders(
71 headers.c_str(), headers.size());
72 responseinfo.socket_address = net::HostPortPair("1.2.3.4", 80);
73 responseinfo.headers = new net::HttpResponseHeaders(raw_headers);
75 base::Pickle pickle;
76 responseinfo.Persist(&pickle, false, false);
78 scoped_refptr<net::WrappedIOBuffer> buf(new net::WrappedIOBuffer(
79 reinterpret_cast<const char*>(pickle.data())));
80 int len = static_cast<int>(pickle.size());
82 net::TestCompletionCallback cb;
83 int rv = entry->WriteData(0, 0, buf.get(), len, cb.callback(), true);
84 ASSERT_EQ(len, cb.GetResult(rv));
87 void WriteData(disk_cache::Entry* entry, const std::string& data) {
88 if (data.empty())
89 return;
91 int len = data.length();
92 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(len));
93 memcpy(buf->data(), data.data(), data.length());
95 net::TestCompletionCallback cb;
96 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
97 ASSERT_EQ(len, cb.GetResult(rv));
100 void WriteToEntry(disk_cache::Backend* cache, const std::string& key,
101 const std::string& headers, const std::string& data) {
102 net::TestCompletionCallback cb;
103 disk_cache::Entry* entry;
104 int rv = cache->CreateEntry(key, &entry, cb.callback());
105 rv = cb.GetResult(rv);
106 if (rv != net::OK) {
107 rv = cache->OpenEntry(key, &entry, cb.callback());
108 ASSERT_EQ(net::OK, cb.GetResult(rv));
111 WriteHeaders(entry, headers);
112 WriteData(entry, data);
113 entry->Close();
116 void FillCache(net::URLRequestContextGetter* context_getter) {
117 net::TestCompletionCallback cb;
118 disk_cache::Backend* cache;
119 int rv =
120 context_getter->GetURLRequestContext()->http_transaction_factory()->
121 GetCache()->GetBackend(&cache, cb.callback());
122 ASSERT_EQ(net::OK, cb.GetResult(rv));
124 WriteToEntry(cache, kMalwareURL, kMalwareHeaders, kMalwareData);
125 WriteToEntry(cache, kLandingURL, kLandingHeaders, kLandingData);
128 // Lets us provide a MockURLRequestContext with an HTTP Cache we pre-populate.
129 // Also exposes the constructor.
130 class MalwareDetailsWrap : public MalwareDetails {
131 public:
132 MalwareDetailsWrap(
133 SafeBrowsingUIManager* ui_manager,
134 WebContents* web_contents,
135 const SafeBrowsingUIManager::UnsafeResource& unsafe_resource,
136 net::URLRequestContextGetter* request_context_getter)
137 : MalwareDetails(ui_manager, web_contents, unsafe_resource) {
138 request_context_getter_ = request_context_getter;
141 private:
142 ~MalwareDetailsWrap() override {}
145 class MockSafeBrowsingUIManager : public SafeBrowsingUIManager {
146 public:
147 base::RunLoop* run_loop_;
148 // The safe browsing UI manager does not need a service for this test.
149 MockSafeBrowsingUIManager()
150 : SafeBrowsingUIManager(NULL), run_loop_(NULL) {}
152 // When the MalwareDetails is done, this is called.
153 void SendSerializedMalwareDetails(const std::string& serialized) override {
154 DVLOG(1) << "SendSerializedMalwareDetails";
155 run_loop_->Quit();
156 run_loop_ = NULL;
157 serialized_ = serialized;
160 // Used to synchronize SendSerializedMalwareDetails() with
161 // WaitForSerializedReport(). RunLoop::RunUntilIdle() is not sufficient
162 // because the MessageLoop task queue completely drains at some point
163 // between the send and the wait.
164 void SetRunLoopToQuit(base::RunLoop* run_loop) {
165 DCHECK(run_loop_ == NULL);
166 run_loop_ = run_loop;
169 const std::string& GetSerialized() {
170 return serialized_;
173 private:
174 ~MockSafeBrowsingUIManager() override {}
176 std::string serialized_;
177 DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingUIManager);
180 } // namespace.
182 class MalwareDetailsTest : public ChromeRenderViewHostTestHarness {
183 public:
184 typedef SafeBrowsingUIManager::UnsafeResource UnsafeResource;
186 MalwareDetailsTest()
187 : ui_manager_(new MockSafeBrowsingUIManager()) {
190 void SetUp() override {
191 ChromeRenderViewHostTestHarness::SetUp();
192 ASSERT_TRUE(profile()->CreateHistoryService(
193 true /* delete_file */, false /* no_db */));
196 void TearDown() override {
197 profile()->DestroyHistoryService();
198 ChromeRenderViewHostTestHarness::TearDown();
201 static bool ResourceLessThan(
202 const ClientMalwareReportRequest::Resource* lhs,
203 const ClientMalwareReportRequest::Resource* rhs) {
204 return lhs->id() < rhs->id();
207 std::string WaitForSerializedReport(MalwareDetails* report) {
208 BrowserThread::PostTask(
209 BrowserThread::IO,
210 FROM_HERE,
211 base::Bind(&MalwareDetails::FinishCollection, report));
212 // Wait for the callback (SendSerializedMalwareDetails).
213 DVLOG(1) << "Waiting for SendSerializedMalwareDetails";
214 base::RunLoop run_loop;
215 ui_manager_->SetRunLoopToQuit(&run_loop);
216 run_loop.Run();
217 return ui_manager_->GetSerialized();
220 history::HistoryService* history_service() {
221 return HistoryServiceFactory::GetForProfile(
222 profile(), ServiceAccessType::EXPLICIT_ACCESS);
225 protected:
226 void InitResource(UnsafeResource* resource,
227 bool is_subresource,
228 const GURL& url) {
229 resource->url = url;
230 resource->is_subresource = is_subresource;
231 resource->threat_type = SB_THREAT_TYPE_URL_MALWARE;
232 resource->render_process_host_id =
233 web_contents()->GetRenderProcessHost()->GetID();
234 resource->render_view_id =
235 web_contents()->GetRenderViewHost()->GetRoutingID();
238 void VerifyResults(const ClientMalwareReportRequest& report_pb,
239 const ClientMalwareReportRequest& expected_pb) {
240 EXPECT_EQ(expected_pb.malware_url(), report_pb.malware_url());
241 EXPECT_EQ(expected_pb.page_url(), report_pb.page_url());
242 EXPECT_EQ(expected_pb.referrer_url(), report_pb.referrer_url());
244 ASSERT_EQ(expected_pb.resources_size(), report_pb.resources_size());
245 // Sort the resources, to make the test deterministic
246 std::vector<const ClientMalwareReportRequest::Resource*> resources;
247 for (int i = 0; i < report_pb.resources_size(); ++i) {
248 const ClientMalwareReportRequest::Resource& resource =
249 report_pb.resources(i);
250 resources.push_back(&resource);
252 std::sort(resources.begin(), resources.end(),
253 &MalwareDetailsTest::ResourceLessThan);
255 std::vector<const ClientMalwareReportRequest::Resource*> expected;
256 for (int i = 0; i < report_pb.resources_size(); ++i) {
257 const ClientMalwareReportRequest::Resource& resource =
258 expected_pb.resources(i);
259 expected.push_back(&resource);
261 std::sort(expected.begin(), expected.end(),
262 &MalwareDetailsTest::ResourceLessThan);
264 for (uint32 i = 0; i < expected.size(); ++i) {
265 VerifyResource(resources[i], expected[i]);
268 EXPECT_EQ(expected_pb.complete(), report_pb.complete());
271 void VerifyResource(const ClientMalwareReportRequest::Resource* resource,
272 const ClientMalwareReportRequest::Resource* expected) {
273 EXPECT_EQ(expected->id(), resource->id());
274 EXPECT_EQ(expected->url(), resource->url());
275 EXPECT_EQ(expected->parent_id(), resource->parent_id());
276 ASSERT_EQ(expected->child_ids_size(), resource->child_ids_size());
277 for (int i = 0; i < expected->child_ids_size(); i++) {
278 EXPECT_EQ(expected->child_ids(i), resource->child_ids(i));
281 // Verify HTTP Responses
282 if (expected->has_response()) {
283 ASSERT_TRUE(resource->has_response());
284 EXPECT_EQ(expected->response().firstline().code(),
285 resource->response().firstline().code());
287 ASSERT_EQ(expected->response().headers_size(),
288 resource->response().headers_size());
289 for (int i = 0; i < expected->response().headers_size(); ++i) {
290 EXPECT_EQ(expected->response().headers(i).name(),
291 resource->response().headers(i).name());
292 EXPECT_EQ(expected->response().headers(i).value(),
293 resource->response().headers(i).value());
296 EXPECT_EQ(expected->response().body(), resource->response().body());
297 EXPECT_EQ(expected->response().bodylength(),
298 resource->response().bodylength());
299 EXPECT_EQ(expected->response().bodydigest(),
300 resource->response().bodydigest());
303 // Verify IP:port pair
304 EXPECT_EQ(expected->response().remote_ip(),
305 resource->response().remote_ip());
308 // Adds a page to history.
309 // The redirects is the redirect url chain leading to the url.
310 void AddPageToHistory(const GURL& url,
311 history::RedirectList* redirects) {
312 // The last item of the redirect chain has to be the final url when adding
313 // to history backend.
314 redirects->push_back(url);
315 history_service()->AddPage(
316 url, base::Time::Now(), reinterpret_cast<history::ContextID>(1), 0,
317 GURL(), *redirects, ui::PAGE_TRANSITION_TYPED,
318 history::SOURCE_BROWSED, false);
321 scoped_refptr<MockSafeBrowsingUIManager> ui_manager_;
324 // Tests creating a simple malware report.
325 TEST_F(MalwareDetailsTest, MalwareSubResource) {
326 // Start a load.
327 controller().LoadURL(
328 GURL(kLandingURL),
329 content::Referrer(GURL(kReferrerURL), blink::WebReferrerPolicyDefault),
330 ui::PAGE_TRANSITION_TYPED, std::string());
332 UnsafeResource resource;
333 InitResource(&resource, true, GURL(kMalwareURL));
335 scoped_refptr<MalwareDetailsWrap> report =
336 new MalwareDetailsWrap(ui_manager_.get(), web_contents(), resource, NULL);
338 std::string serialized = WaitForSerializedReport(report.get());
340 ClientMalwareReportRequest actual;
341 actual.ParseFromString(serialized);
343 ClientMalwareReportRequest expected;
344 expected.set_malware_url(kMalwareURL);
345 expected.set_page_url(kLandingURL);
346 // Note that the referrer policy is not actually enacted here, since that's
347 // done in Blink.
348 expected.set_referrer_url(kReferrerURL);
350 ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources();
351 pb_resource->set_id(0);
352 pb_resource->set_url(kLandingURL);
353 pb_resource = expected.add_resources();
354 pb_resource->set_id(1);
355 pb_resource->set_url(kMalwareURL);
356 pb_resource = expected.add_resources();
357 pb_resource->set_id(2);
358 pb_resource->set_url(kReferrerURL);
360 VerifyResults(actual, expected);
363 // Tests creating a simple malware report where the subresource has a
364 // different original_url.
365 TEST_F(MalwareDetailsTest, MalwareSubResourceWithOriginalUrl) {
366 controller().LoadURL(GURL(kLandingURL), content::Referrer(),
367 ui::PAGE_TRANSITION_TYPED, std::string());
369 UnsafeResource resource;
370 InitResource(&resource, true, GURL(kMalwareURL));
371 resource.original_url = GURL(kOriginalLandingURL);
373 scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap(
374 ui_manager_.get(), web_contents(), resource, NULL);
376 std::string serialized = WaitForSerializedReport(report.get());
378 ClientMalwareReportRequest actual;
379 actual.ParseFromString(serialized);
381 ClientMalwareReportRequest expected;
382 expected.set_malware_url(kMalwareURL);
383 expected.set_page_url(kLandingURL);
384 expected.set_referrer_url("");
386 ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources();
387 pb_resource->set_id(0);
388 pb_resource->set_url(kLandingURL);
390 pb_resource = expected.add_resources();
391 pb_resource->set_id(1);
392 pb_resource->set_url(kOriginalLandingURL);
394 pb_resource = expected.add_resources();
395 pb_resource->set_id(2);
396 pb_resource->set_url(kMalwareURL);
397 // The Resource for kMalwareUrl should have the Resource for
398 // kOriginalLandingURL (with id 1) as parent.
399 pb_resource->set_parent_id(1);
401 VerifyResults(actual, expected);
404 // Tests creating a malware report with data from the renderer.
405 TEST_F(MalwareDetailsTest, MalwareDOMDetails) {
406 controller().LoadURL(GURL(kLandingURL), content::Referrer(),
407 ui::PAGE_TRANSITION_TYPED, std::string());
409 UnsafeResource resource;
410 InitResource(&resource, true, GURL(kMalwareURL));
412 scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap(
413 ui_manager_.get(), web_contents(), resource, NULL);
415 // Send a message from the DOM, with 2 nodes, a parent and a child.
416 std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node> params;
417 SafeBrowsingHostMsg_MalwareDOMDetails_Node child_node;
418 child_node.url = GURL(kDOMChildURL);
419 child_node.tag_name = "iframe";
420 child_node.parent = GURL(kDOMParentURL);
421 params.push_back(child_node);
422 SafeBrowsingHostMsg_MalwareDOMDetails_Node parent_node;
423 parent_node.url = GURL(kDOMParentURL);
424 parent_node.children.push_back(GURL(kDOMChildURL));
425 params.push_back(parent_node);
426 report->OnReceivedMalwareDOMDetails(params);
428 std::string serialized = WaitForSerializedReport(report.get());
429 ClientMalwareReportRequest actual;
430 actual.ParseFromString(serialized);
432 ClientMalwareReportRequest expected;
433 expected.set_malware_url(kMalwareURL);
434 expected.set_page_url(kLandingURL);
435 expected.set_referrer_url("");
437 ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources();
438 pb_resource->set_id(0);
439 pb_resource->set_url(kLandingURL);
441 pb_resource = expected.add_resources();
442 pb_resource->set_id(1);
443 pb_resource->set_url(kMalwareURL);
445 pb_resource = expected.add_resources();
446 pb_resource->set_id(2);
447 pb_resource->set_url(kDOMChildURL);
448 pb_resource->set_parent_id(3);
450 pb_resource = expected.add_resources();
451 pb_resource->set_id(3);
452 pb_resource->set_url(kDOMParentURL);
453 pb_resource->add_child_ids(2);
454 expected.set_complete(false); // Since the cache was missing.
456 VerifyResults(actual, expected);
459 // Tests creating a malware report where there are redirect urls to an unsafe
460 // resource url
461 TEST_F(MalwareDetailsTest, MalwareWithRedirectUrl) {
462 controller().LoadURL(GURL(kLandingURL), content::Referrer(),
463 ui::PAGE_TRANSITION_TYPED, std::string());
465 UnsafeResource resource;
466 InitResource(&resource, true, GURL(kMalwareURL));
467 resource.original_url = GURL(kOriginalLandingURL);
469 // add some redirect urls
470 resource.redirect_urls.push_back(GURL(kFirstRedirectURL));
471 resource.redirect_urls.push_back(GURL(kSecondRedirectURL));
472 resource.redirect_urls.push_back(GURL(kMalwareURL));
474 scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap(
475 ui_manager_.get(), web_contents(), resource, NULL);
477 std::string serialized = WaitForSerializedReport(report.get());
478 ClientMalwareReportRequest actual;
479 actual.ParseFromString(serialized);
481 ClientMalwareReportRequest expected;
482 expected.set_malware_url(kMalwareURL);
483 expected.set_page_url(kLandingURL);
484 expected.set_referrer_url("");
486 ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources();
487 pb_resource->set_id(0);
488 pb_resource->set_url(kLandingURL);
490 pb_resource = expected.add_resources();
491 pb_resource->set_id(1);
492 pb_resource->set_url(kOriginalLandingURL);
494 pb_resource = expected.add_resources();
495 pb_resource->set_id(2);
496 pb_resource->set_url(kMalwareURL);
497 pb_resource->set_parent_id(4);
499 pb_resource = expected.add_resources();
500 pb_resource->set_id(3);
501 pb_resource->set_url(kFirstRedirectURL);
502 pb_resource->set_parent_id(1);
504 pb_resource = expected.add_resources();
505 pb_resource->set_id(4);
506 pb_resource->set_url(kSecondRedirectURL);
507 pb_resource->set_parent_id(3);
509 VerifyResults(actual, expected);
512 // Tests the interaction with the HTTP cache.
513 TEST_F(MalwareDetailsTest, HTTPCache) {
514 controller().LoadURL(GURL(kLandingURL), content::Referrer(),
515 ui::PAGE_TRANSITION_TYPED, std::string());
517 UnsafeResource resource;
518 InitResource(&resource, true, GURL(kMalwareURL));
520 scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap(
521 ui_manager_.get(), web_contents(), resource,
522 profile()->GetRequestContext());
524 BrowserThread::PostTask(
525 BrowserThread::IO, FROM_HERE,
526 base::Bind(&FillCache,
527 make_scoped_refptr(profile()->GetRequestContext())));
529 // The cache collection starts after the IPC from the DOM is fired.
530 std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node> params;
531 report->OnReceivedMalwareDOMDetails(params);
533 // Let the cache callbacks complete.
534 base::RunLoop().RunUntilIdle();
536 DVLOG(1) << "Getting serialized report";
537 std::string serialized = WaitForSerializedReport(report.get());
538 ClientMalwareReportRequest actual;
539 actual.ParseFromString(serialized);
541 ClientMalwareReportRequest expected;
542 expected.set_malware_url(kMalwareURL);
543 expected.set_page_url(kLandingURL);
544 expected.set_referrer_url("");
546 ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources();
547 pb_resource->set_id(0);
548 pb_resource->set_url(kLandingURL);
549 safe_browsing::ClientMalwareReportRequest::HTTPResponse* pb_response =
550 pb_resource->mutable_response();
551 pb_response->mutable_firstline()->set_code(200);
552 safe_browsing::ClientMalwareReportRequest::HTTPHeader* pb_header =
553 pb_response->add_headers();
554 pb_header->set_name("Content-Type");
555 pb_header->set_value("text/html");
556 pb_header = pb_response->add_headers();
557 pb_header->set_name("Content-Length");
558 pb_header->set_value("1024");
559 pb_header = pb_response->add_headers();
560 pb_header->set_name("Set-Cookie");
561 pb_header->set_value(""); // The cookie is dropped.
562 pb_response->set_body(kLandingData);
563 pb_response->set_bodylength(47);
564 pb_response->set_bodydigest("5abb4e63d806ec2c16a40b2699700554");
565 pb_response->set_remote_ip("1.2.3.4:80");
567 pb_resource = expected.add_resources();
568 pb_resource->set_id(1);
569 pb_resource->set_url(kMalwareURL);
570 pb_response = pb_resource->mutable_response();
571 pb_response->mutable_firstline()->set_code(200);
572 pb_header = pb_response->add_headers();
573 pb_header->set_name("Content-Type");
574 pb_header->set_value("image/jpeg");
575 pb_response->set_body(kMalwareData);
576 pb_response->set_bodylength(10);
577 pb_response->set_bodydigest("581373551c43d4cf33bfb3b26838ff95");
578 pb_response->set_remote_ip("1.2.3.4:80");
579 expected.set_complete(true);
581 VerifyResults(actual, expected);
584 // Tests the interaction with the HTTP cache (where the cache is empty).
585 TEST_F(MalwareDetailsTest, HTTPCacheNoEntries) {
586 controller().LoadURL(GURL(kLandingURL), content::Referrer(),
587 ui::PAGE_TRANSITION_TYPED, std::string());
589 UnsafeResource resource;
590 InitResource(&resource, true, GURL(kMalwareURL));
592 scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap(
593 ui_manager_.get(), web_contents(), resource,
594 profile()->GetRequestContext());
596 // No call to FillCache
598 // The cache collection starts after the IPC from the DOM is fired.
599 std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node> params;
600 report->OnReceivedMalwareDOMDetails(params);
602 // Let the cache callbacks complete.
603 base::RunLoop().RunUntilIdle();
605 DVLOG(1) << "Getting serialized report";
606 std::string serialized = WaitForSerializedReport(report.get());
607 ClientMalwareReportRequest actual;
608 actual.ParseFromString(serialized);
610 ClientMalwareReportRequest expected;
611 expected.set_malware_url(kMalwareURL);
612 expected.set_page_url(kLandingURL);
613 expected.set_referrer_url("");
615 ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources();
616 pb_resource->set_id(0);
617 pb_resource->set_url(kLandingURL);
618 pb_resource = expected.add_resources();
619 pb_resource->set_id(1);
620 pb_resource->set_url(kMalwareURL);
621 expected.set_complete(true);
623 VerifyResults(actual, expected);
626 // Test getting redirects from history service.
627 TEST_F(MalwareDetailsTest, HistoryServiceUrls) {
628 // Add content to history service.
629 // There are two redirect urls before reacing malware url:
630 // kFirstRedirectURL -> kSecondRedirectURL -> kMalwareURL
631 GURL baseurl(kMalwareURL);
632 history::RedirectList redirects;
633 redirects.push_back(GURL(kFirstRedirectURL));
634 redirects.push_back(GURL(kSecondRedirectURL));
635 AddPageToHistory(baseurl, &redirects);
636 // Wait for history service operation finished.
637 profile()->BlockUntilHistoryProcessesPendingRequests();
639 controller().LoadURL(GURL(kLandingURL), content::Referrer(),
640 ui::PAGE_TRANSITION_TYPED, std::string());
642 UnsafeResource resource;
643 InitResource(&resource, true, GURL(kMalwareURL));
644 scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap(
645 ui_manager_.get(), web_contents(), resource, NULL);
647 // The redirects collection starts after the IPC from the DOM is fired.
648 std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node> params;
649 report->OnReceivedMalwareDOMDetails(params);
651 // Let the redirects callbacks complete.
652 base::RunLoop().RunUntilIdle();
654 std::string serialized = WaitForSerializedReport(report.get());
655 ClientMalwareReportRequest actual;
656 actual.ParseFromString(serialized);
658 ClientMalwareReportRequest expected;
659 expected.set_malware_url(kMalwareURL);
660 expected.set_page_url(kLandingURL);
661 expected.set_referrer_url("");
663 ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources();
664 pb_resource->set_id(0);
665 pb_resource->set_url(kLandingURL);
666 pb_resource = expected.add_resources();
667 pb_resource->set_id(1);
668 pb_resource->set_parent_id(2);
669 pb_resource->set_url(kMalwareURL);
670 pb_resource = expected.add_resources();
671 pb_resource->set_id(2);
672 pb_resource->set_parent_id(3);
673 pb_resource->set_url(kSecondRedirectURL);
674 pb_resource = expected.add_resources();
675 pb_resource->set_id(3);
676 pb_resource->set_url(kFirstRedirectURL);
678 VerifyResults(actual, expected);