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

Unified Diff: chrome/browser/safe_browsing/malware_details_unittest.cc

Issue 6611023: The optional Malware Details also collects HTTP cache information. See design... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/safe_browsing/malware_details_unittest.cc
===================================================================
--- chrome/browser/safe_browsing/malware_details_unittest.cc (revision 81745)
+++ chrome/browser/safe_browsing/malware_details_unittest.cc (working copy)
@@ -4,42 +4,205 @@
#include <algorithm>
+#include "base/pickle.h"
+#include "base/time.h"
+#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/safe_browsing/malware_details.h"
#include "chrome/browser/safe_browsing/report.pb.h"
+#include "chrome/common/net/test_url_fetcher_factory.h"
+#include "chrome/common/render_messages.h"
#include "chrome/common/safe_browsing/safebrowsing_messages.h"
+#include "chrome/test/testing_profile.h"
+#include "chrome/test/test_url_request_context_getter.h"
#include "content/browser/browser_thread.h"
#include "content/browser/renderer_host/test_render_view_host.h"
#include "content/browser/tab_contents/navigation_entry.h"
#include "content/browser/tab_contents/test_tab_contents.h"
+#include "net/base/io_buffer.h"
+#include "net/base/test_completion_callback.h"
+#include "net/disk_cache/disk_cache.h"
+#include "net/http/http_cache.h"
+#include "net/http/http_response_info.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
static const char* kOriginalLandingURL = "http://www.originallandingpage.com/";
-static const char* kLandingURL = "http://www.landingpage.com/";
-static const char* kMalwareURL = "http://www.malware.com/";
static const char* kHttpsURL = "https://www.url.com/";
static const char* kDOMChildURL = "http://www.domparent.com/";
static const char* kDOMParentURL = "http://www.domchild.com/";
static const char* kFirstRedirectURL = "http://redirectone.com/";
static const char* kSecondRedirectURL = "http://redirecttwo.com/";
+static const char* kMalwareURL = "http://www.malware.com/";
+static const char* kMalwareHeaders =
+ "HTTP/1.1 200 OK\n"
+ "Content-Type: image/jpeg\n";
+static const char* kMalwareData = "exploit();";
+
+static const char* kLandingURL = "http://www.landingpage.com/";
+static const char* kLandingHeaders =
+ "HTTP/1.1 200 OK\n"
+ "Content-Type: text/html\n"
+ "Content-Length: 1024\n"
+ "Set-Cookie: tastycookie\n"; // This header is stripped.
+static const char* kLandingData = "<iframe src='http://www.malware.com'>";
+
using safe_browsing::ClientMalwareReportRequest;
-class MalwareDetailsTest : public RenderViewHostTestHarness {
+namespace {
+
+void WriteHeaders(disk_cache::Entry* entry, const std::string headers) {
+ net::HttpResponseInfo responseinfo;
+ std::string raw_headers = net::HttpUtil::AssembleRawHeaders(
+ headers.c_str(), headers.size());
+ responseinfo.headers = new net::HttpResponseHeaders(raw_headers);
+
+ Pickle pickle;
+ responseinfo.Persist(&pickle, false, false);
+
+ scoped_refptr<net::WrappedIOBuffer> buf(new net::WrappedIOBuffer(
+ reinterpret_cast<const char*>(pickle.data())));
+ int len = static_cast<int>(pickle.size());
+
+ TestCompletionCallback cb;
+ int rv = entry->WriteData(0, 0, buf, len, &cb, true);
+ ASSERT_EQ(len, cb.GetResult(rv));
+}
+
+void WriteData(disk_cache::Entry* entry, const std::string data) {
+ if (data.empty())
+ return;
+
+ int len = data.length();
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(len));
+ memcpy(buf->data(), data.data(), data.length());
+
+ TestCompletionCallback cb;
+ int rv = entry->WriteData(1, 0, buf, len, &cb, true);
+ ASSERT_EQ(len, cb.GetResult(rv));
+}
+
+void WriteToEntry(disk_cache::Backend* cache, const std::string key,
+ const std::string headers, const std::string data) {
+ TestCompletionCallback cb;
+ disk_cache::Entry* entry;
+ int rv = cache->CreateEntry(key, &entry, &cb);
+ rv = cb.GetResult(rv);
+ if (rv != net::OK) {
+ rv = cache->OpenEntry(key, &entry, &cb);
+ ASSERT_EQ(net::OK, cb.GetResult(rv));
+ }
+
+ WriteHeaders(entry, headers);
+ WriteData(entry, data);
+
+ entry->Close();
+}
+
+void FillCache(net::URLRequestContext* context) {
+ TestCompletionCallback cb;
+ disk_cache::Backend* cache;
+ int rv =
+ context->http_transaction_factory()->GetCache()->GetBackend(&cache, &cb);
+ ASSERT_EQ(net::OK, cb.GetResult(rv));
+
+ std::string empty;
+ WriteToEntry(cache, kMalwareURL, kMalwareHeaders, kMalwareData);
+ WriteToEntry(cache, kLandingURL, kLandingHeaders, kLandingData);
+}
+
+void QuitUIMessageLoop() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ BrowserThread::PostTask(BrowserThread::UI,
+ FROM_HERE,
+ new MessageLoop::QuitTask());
+}
+
+// Lets us provide a MockURLRequestContext with an HTTP Cache we pre-populate.
+// Also exposes the constructor.
+class MalwareDetailsWrap : public MalwareDetails {
public:
+ MalwareDetailsWrap(SafeBrowsingService* sb_service,
+ TabContents* tab_contents,
+ const SafeBrowsingService::UnsafeResource& unsafe_resource,
+ net::URLRequestContextGetter* request_context_getter)
+ : MalwareDetails(sb_service, tab_contents, unsafe_resource) {
+ request_context_getter_ = request_context_getter;
+ }
+
+ virtual ~MalwareDetailsWrap() {}
+};
+
+class MockSafeBrowsingService : public SafeBrowsingService {
+ public:
+ MockSafeBrowsingService() {}
+ virtual ~MockSafeBrowsingService() {}
+
+ // When the MalwareDetails is done, this is called.
+ virtual void SendSerializedMalwareDetails(const std::string& serialized) {
+ DVLOG(1) << "SendSerializedMalwareDetails";
+ // Notify WaitForSerializedReport.
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ NewRunnableFunction(&QuitUIMessageLoop));
+ serialized_ = serialized;
+ }
+
+ const std::string& GetSerialized() {
+ return serialized_;
+ }
+
+ private:
+ std::string serialized_;
+ DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingService);
+};
+
+} // namespace.
+
+class MalwareDetailsTest :
+ public RenderViewHostTestHarness {
+ public:
MalwareDetailsTest()
- : ui_thread_(BrowserThread::UI, MessageLoop::current()),
- io_thread_(BrowserThread::IO, MessageLoop::current()) {
+ : ui_thread_(BrowserThread::UI, &message_loop_),
+ io_thread_(NULL),
+ sb_service_(new MockSafeBrowsingService()) {
}
virtual void SetUp() {
RenderViewHostTestHarness::SetUp();
+ request_context_getter_ = new TestURLRequestContextGetter();
+
+ // The URLFetcher checks that the messageloop type is IO.
+ io_thread_.reset(new BrowserThread(BrowserThread::IO));
+ ASSERT_TRUE(io_thread_->StartWithOptions(
+ base::Thread::Options(MessageLoop::TYPE_IO, 0)));
}
+ virtual void TearDown() {
+ io_thread_.reset();
+ RenderViewHostTestHarness::TearDown();
+ }
+
static bool ResourceLessThan(
const ClientMalwareReportRequest::Resource* lhs,
const ClientMalwareReportRequest::Resource* rhs) {
return lhs->id() < rhs->id();
}
+ std::string WaitForSerializedReport(MalwareDetails* report) {
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ NewRunnableMethod(
+ report, &MalwareDetails::FinishCollection));
+ // Wait for the callback (SendSerializedMalwareDetails).
+ DVLOG(1) << "Waiting for SendSerializedMalwareDetails";
+ MessageLoop::current()->Run();
+ return sb_service_->GetSerialized();
+ }
+
protected:
void InitResource(SafeBrowsingService::UnsafeResource* resource,
ResourceType::Type resource_type,
@@ -79,18 +242,49 @@
&MalwareDetailsTest::ResourceLessThan);
for (uint32 i = 0; i < expected.size(); ++i) {
- EXPECT_EQ(expected[i]->id(), resources[i]->id());
- EXPECT_EQ(expected[i]->url(), resources[i]->url());
- EXPECT_EQ(expected[i]->parent_id(), resources[i]->parent_id());
- ASSERT_EQ(expected[i]->child_ids_size(), resources[i]->child_ids_size());
- for (int j = 0; j < expected[i]->child_ids_size(); j++) {
- EXPECT_EQ(expected[i]->child_ids(j), resources[i]->child_ids(j));
+ VerifyResource(resources[i], expected[i]);
+ }
+
+ EXPECT_EQ(expected_pb.complete(), report_pb.complete());
+ }
+
+ void VerifyResource(const ClientMalwareReportRequest::Resource* resource,
+ const ClientMalwareReportRequest::Resource* expected) {
+ EXPECT_EQ(expected->id(), resource->id());
+ EXPECT_EQ(expected->url(), resource->url());
+ EXPECT_EQ(expected->parent_id(), resource->parent_id());
+ ASSERT_EQ(expected->child_ids_size(), resource->child_ids_size());
+ for (int i = 0; i < expected->child_ids_size(); i++) {
+ EXPECT_EQ(expected->child_ids(i), resource->child_ids(i));
+ }
+
+ // Verify HTTP Responses
+ if (expected->has_response()) {
+ ASSERT_TRUE(resource->has_response());
+ EXPECT_EQ(expected->response().firstline().code(),
+ resource->response().firstline().code());
+
+ ASSERT_EQ(expected->response().headers_size(),
+ resource->response().headers_size());
+ for (int i = 0; i < expected->response().headers_size(); ++i) {
+ EXPECT_EQ(expected->response().headers(i).name(),
+ resource->response().headers(i).name());
+ EXPECT_EQ(expected->response().headers(i).value(),
+ resource->response().headers(i).value());
}
+
+ EXPECT_EQ(expected->response().body(), resource->response().body());
+ EXPECT_EQ(expected->response().bodylength(),
+ resource->response().bodylength());
+ EXPECT_EQ(expected->response().bodydigest(),
+ resource->response().bodydigest());
}
}
BrowserThread ui_thread_;
- BrowserThread io_thread_;
+ scoped_ptr<BrowserThread> io_thread_;
+ scoped_refptr<MockSafeBrowsingService> sb_service_;
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
};
// Tests creating a simple malware report.
@@ -101,12 +295,13 @@
SafeBrowsingService::UnsafeResource resource;
InitResource(&resource, ResourceType::SUB_RESOURCE, GURL(kMalwareURL));
- scoped_refptr<MalwareDetails> report = MalwareDetails::NewMalwareDetails(
- contents(), resource);
+ scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap(
+ sb_service_, contents(), resource, NULL);
- scoped_ptr<const std::string> serialized(report->GetSerializedReport());
+ std::string serialized = WaitForSerializedReport(report);
+
ClientMalwareReportRequest actual;
- actual.ParseFromString(*serialized);
+ actual.ParseFromString(serialized);
ClientMalwareReportRequest expected;
expected.set_malware_url(kMalwareURL);
@@ -132,12 +327,13 @@
InitResource(&resource, ResourceType::SUB_RESOURCE, GURL(kMalwareURL));
resource.original_url = GURL(kOriginalLandingURL);
- scoped_refptr<MalwareDetails> report = MalwareDetails::NewMalwareDetails(
- contents(), resource);
+ scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap(
+ sb_service_.get(), contents(), resource, NULL);
- scoped_ptr<const std::string> serialized(report->GetSerializedReport());
+ std::string serialized = WaitForSerializedReport(report);
+
ClientMalwareReportRequest actual;
- actual.ParseFromString(*serialized);
+ actual.ParseFromString(serialized);
ClientMalwareReportRequest expected;
expected.set_malware_url(kMalwareURL);
@@ -169,8 +365,8 @@
SafeBrowsingService::UnsafeResource resource;
InitResource(&resource, ResourceType::SUB_RESOURCE, GURL(kMalwareURL));
- scoped_refptr<MalwareDetails> report = MalwareDetails::NewMalwareDetails(
- contents(), resource);
+ scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap(
+ sb_service_.get(), contents(), resource, NULL);
// Send a message from the DOM, with 2 nodes, a parent and a child.
std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node> params;
@@ -187,9 +383,9 @@
MessageLoop::current()->RunAllPending();
- scoped_ptr<const std::string> serialized(report->GetSerializedReport());
+ std::string serialized = WaitForSerializedReport(report);
ClientMalwareReportRequest actual;
- actual.ParseFromString(*serialized);
+ actual.ParseFromString(serialized);
ClientMalwareReportRequest expected;
expected.set_malware_url(kMalwareURL);
@@ -213,6 +409,7 @@
pb_resource->set_id(3);
pb_resource->set_url(kDOMParentURL);
pb_resource->add_child_ids(2);
+ expected.set_complete(false); // Since the cache was missing.
VerifyResults(actual, expected);
}
@@ -222,12 +419,12 @@
controller().LoadURL(GURL(kHttpsURL), GURL(), PageTransition::TYPED);
SafeBrowsingService::UnsafeResource resource;
InitResource(&resource, ResourceType::SUB_RESOURCE, GURL(kMalwareURL));
- scoped_refptr<MalwareDetails> report = MalwareDetails::NewMalwareDetails(
- contents(), resource);
+ scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap(
+ sb_service_.get(), contents(), resource, NULL);
- scoped_ptr<const std::string> serialized(report->GetSerializedReport());
+ std::string serialized = WaitForSerializedReport(report);
ClientMalwareReportRequest actual;
- actual.ParseFromString(*serialized);
+ actual.ParseFromString(serialized);
ClientMalwareReportRequest expected;
expected.set_malware_url(kMalwareURL); // No page_url
@@ -253,12 +450,12 @@
resource.redirect_urls.push_back(GURL(kSecondRedirectURL));
resource.redirect_urls.push_back(GURL(kMalwareURL));
- scoped_refptr<MalwareDetails> report = MalwareDetails::NewMalwareDetails(
- contents(), resource);
+ scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap(
+ sb_service_.get(), contents(), resource, NULL);
- scoped_ptr<const std::string> serialized(report->GetSerializedReport());
+ std::string serialized = WaitForSerializedReport(report);
ClientMalwareReportRequest actual;
- actual.ParseFromString(*serialized);
+ actual.ParseFromString(serialized);
ClientMalwareReportRequest expected;
expected.set_malware_url(kMalwareURL);
@@ -290,3 +487,108 @@
VerifyResults(actual, expected);
}
+
+// Tests the interaction with the HTTP cache.
+TEST_F(MalwareDetailsTest, HTTPCache) {
+ controller().LoadURL(GURL(kLandingURL), GURL(), PageTransition::TYPED);
+
+ SafeBrowsingService::UnsafeResource resource;
+ InitResource(&resource, ResourceType::SUB_RESOURCE, GURL(kMalwareURL));
+
+ scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap(
+ sb_service_.get(), contents(), resource, request_context_getter_.get());
+
+ FillCache(request_context_getter_->GetURLRequestContext());
+
+ // The cache collection starts after the IPC from the DOM is fired.
+ std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node> params;
+ report->OnReceivedMalwareDOMDetails(params);
+
+ // Let the cache callbacks complete
+ MessageLoop::current()->RunAllPending();
+
+ DVLOG(1) << "Getting serialized report";
+ std::string serialized = WaitForSerializedReport(report);
+ ClientMalwareReportRequest actual;
+ actual.ParseFromString(serialized);
+
+ ClientMalwareReportRequest expected;
+ expected.set_malware_url(kMalwareURL);
+ expected.set_page_url(kLandingURL);
+ expected.set_referrer_url("");
+
+ ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources();
+ pb_resource->set_id(0);
+ pb_resource->set_url(kLandingURL);
+ safe_browsing::ClientMalwareReportRequest::HTTPResponse* pb_response =
+ pb_resource->mutable_response();
+ pb_response->mutable_firstline()->set_code(200);
+ safe_browsing::ClientMalwareReportRequest::HTTPHeader* pb_header =
+ pb_response->add_headers();
+ pb_header->set_name("Content-Type");
+ pb_header->set_value("text/html");
+ pb_header = pb_response->add_headers();
+ pb_header->set_name("Content-Length");
+ pb_header->set_value("1024");
+ pb_header = pb_response->add_headers();
+ pb_header->set_name("Set-Cookie");
+ pb_header->set_value(""); // The cookie is dropped.
+ pb_response->set_body(kLandingData);
+ pb_response->set_bodylength(37);
+ pb_response->set_bodydigest("9ca97475598a79bc1e8fc9bd6c72cd35");
+
+ pb_resource = expected.add_resources();
+ pb_resource->set_id(1);
+ pb_resource->set_url(kMalwareURL);
+ pb_response = pb_resource->mutable_response();
+ pb_response->mutable_firstline()->set_code(200);
+ pb_header = pb_response->add_headers();
+ pb_header->set_name("Content-Type");
+ pb_header->set_value("image/jpeg");
+ pb_response->set_body(kMalwareData);
+ pb_response->set_bodylength(10);
+ pb_response->set_bodydigest("581373551c43d4cf33bfb3b26838ff95");
+ expected.set_complete(true);
+
+ VerifyResults(actual, expected);
+}
+
+// Tests the interaction with the HTTP cache (where the cache is empty).
+TEST_F(MalwareDetailsTest, HTTPCacheNoEntries) {
+ controller().LoadURL(GURL(kLandingURL), GURL(), PageTransition::TYPED);
+
+ SafeBrowsingService::UnsafeResource resource;
+ InitResource(&resource, ResourceType::SUB_RESOURCE, GURL(kMalwareURL));
+
+ scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap(
+ sb_service_.get(), contents(), resource, request_context_getter_.get());
+
+ // No call to FillCache
+
+ // The cache collection starts after the IPC from the DOM is fired.
+ std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node> params;
+ report->OnReceivedMalwareDOMDetails(params);
+
+ // Let the cache callbacks complete
+ MessageLoop::current()->RunAllPending();
+
+ DVLOG(1) << "Getting serialized report";
+ std::string serialized = WaitForSerializedReport(report);
+ ClientMalwareReportRequest actual;
+ actual.ParseFromString(serialized);
+
+ ClientMalwareReportRequest expected;
+ expected.set_malware_url(kMalwareURL);
+ expected.set_page_url(kLandingURL);
+ expected.set_referrer_url("");
+
+ ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources();
+ pb_resource->set_id(0);
+ pb_resource->set_url(kLandingURL);
+ pb_resource = expected.add_resources();
+ pb_resource->set_id(1);
+ pb_resource->set_url(kMalwareURL);
+ expected.set_complete(true);
+
+ VerifyResults(actual, expected);
+}

Powered by Google App Engine
This is Rietveld 408576698