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

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, 10 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 76771)
+++ chrome/browser/safe_browsing/malware_details_unittest.cc (working copy)
@@ -4,28 +4,156 @@
#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/render_messages.h"
#include "chrome/common/render_messages_params.h"
+#include "chrome/test/testing_profile.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"
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 dropped.
+static const char* kLandingData = "<iframe src='http://www.malware.com'>";
+
using safe_browsing::ClientMalwareReportRequest;
-class MalwareDetailsTest : public RenderViewHostTestHarness {
+namespace {
+
+class MockURLRequestContext : public net::URLRequestContext {
public:
+ MockURLRequestContext()
+ : cache_(reinterpret_cast<net::HttpTransactionFactory*>(NULL), NULL,
+ net::HttpCache::DefaultBackend::InMemory(0)) {
+ set_http_transaction_factory(&cache_);
+ }
+
+ private:
+ net::HttpCache cache_;
+};
+
+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);
+}
+
+// Lets us provide a MockURLRequestContext and an InMemory HTTP Cache.
+// Also exposes the constructor.
+class MalwareDetailsWrap : public MalwareDetails {
+ public:
+ MalwareDetailsWrap(TabContents* tab_contents,
+ const SafeBrowsingService::UnsafeResource& unsafe_resource,
+ bool provide_cache)
+ : MalwareDetails(tab_contents, unsafe_resource),
+ request_context_(new MockURLRequestContext()),
+ provide_cache_(provide_cache) {
+ }
+
+ virtual ~MalwareDetailsWrap() {}
+
+ virtual net::URLRequestContext* GetURLRequestContext() {
+ if (provide_cache_) {
+ return request_context_;
+ }
+ return NULL;
+ }
+
+ private:
+ MockURLRequestContext* request_context_;
+ bool provide_cache_;
+};
+
+} // namespace.
+
+class MalwareDetailsTest :
+ public RenderViewHostTestHarness {
+ // public base::RefCountedThreadSafe<MalwareDetailsTest> {
+ public:
MalwareDetailsTest()
: ui_thread_(BrowserThread::UI, MessageLoop::current()),
io_thread_(BrowserThread::IO, MessageLoop::current()) {
@@ -41,6 +169,18 @@
return lhs->id() < rhs->id();
}
+ const std::string* WaitForSerializedReport(MalwareDetails* report) {
+ report->StartCacheCollection(
+ NewCallback(this, &MalwareDetailsTest::OnReportReady));
+ MessageLoop::current()->Run(); // Waits for the callback.
+ return report->GetSerializedReport();
+ }
+
+ void OnReportReady(scoped_refptr<MalwareDetails> report) {
+ LOG(ERROR) << "OnReportReady";
+ MessageLoop::current()->Quit();
+ }
+
protected:
void InitResource(SafeBrowsingService::UnsafeResource* resource,
ResourceType::Type resource_type,
@@ -80,13 +220,42 @@
&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());
}
}
@@ -102,10 +271,11 @@
SafeBrowsingService::UnsafeResource resource;
InitResource(&resource, ResourceType::SUB_RESOURCE, GURL(kMalwareURL));
- scoped_refptr<MalwareDetails> report = MalwareDetails::NewMalwareDetails(
- contents(), resource);
+ scoped_refptr<MalwareDetails> report = new MalwareDetailsWrap(
+ contents(), resource, false);
- scoped_ptr<const std::string> serialized(report->GetSerializedReport());
+ scoped_ptr<const std::string> serialized(WaitForSerializedReport(report));
+
ClientMalwareReportRequest actual;
actual.ParseFromString(*serialized);
@@ -133,10 +303,10 @@
InitResource(&resource, ResourceType::SUB_RESOURCE, GURL(kMalwareURL));
resource.original_url = GURL(kOriginalLandingURL);
- scoped_refptr<MalwareDetails> report = MalwareDetails::NewMalwareDetails(
- contents(), resource);
+ scoped_refptr<MalwareDetails> report = new MalwareDetailsWrap(
+ contents(), resource, false);
- scoped_ptr<const std::string> serialized(report->GetSerializedReport());
+ scoped_ptr<const std::string> serialized(WaitForSerializedReport(report));
ClientMalwareReportRequest actual;
actual.ParseFromString(*serialized);
@@ -170,8 +340,8 @@
SafeBrowsingService::UnsafeResource resource;
InitResource(&resource, ResourceType::SUB_RESOURCE, GURL(kMalwareURL));
- scoped_refptr<MalwareDetails> report = MalwareDetails::NewMalwareDetails(
- contents(), resource);
+ scoped_refptr<MalwareDetails> report = new MalwareDetailsWrap(
+ contents(), resource, false);
// Send a message from the DOM, with 2 nodes, a parent and a child.
ViewHostMsg_MalwareDOMDetails_Params params;
@@ -188,7 +358,7 @@
MessageLoop::current()->RunAllPending();
- scoped_ptr<const std::string> serialized(report->GetSerializedReport());
+ scoped_ptr<const std::string> serialized(WaitForSerializedReport(report));
ClientMalwareReportRequest actual;
actual.ParseFromString(*serialized);
@@ -214,6 +384,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);
}
@@ -223,10 +394,10 @@
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<MalwareDetails> report = new MalwareDetailsWrap(
+ contents(), resource, false);
- scoped_ptr<const std::string> serialized(report->GetSerializedReport());
+ scoped_ptr<const std::string> serialized(WaitForSerializedReport(report));
ClientMalwareReportRequest actual;
actual.ParseFromString(*serialized);
@@ -254,10 +425,10 @@
resource.redirect_urls.push_back(GURL(kSecondRedirectURL));
resource.redirect_urls.push_back(GURL(kMalwareURL));
- scoped_refptr<MalwareDetails> report = MalwareDetails::NewMalwareDetails(
- contents(), resource);
+ scoped_refptr<MalwareDetails> report = new MalwareDetailsWrap(
+ contents(), resource, false);
- scoped_ptr<const std::string> serialized(report->GetSerializedReport());
+ scoped_ptr<const std::string> serialized(WaitForSerializedReport(report));
ClientMalwareReportRequest actual;
actual.ParseFromString(*serialized);
@@ -291,3 +462,105 @@
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(
+ contents(), resource, true);
+
+ FillCache(report->GetURLRequestContext());
+
+ // The cache collection starts after the IPC from the DOM is fired.
+ ViewHostMsg_MalwareDOMDetails_Params params;
+ report->OnReceivedMalwareDOMDetails(params);
+
+ // Let the cache callbacks complete
+ MessageLoop::current()->RunAllPending();
+
+ LOG(INFO) << "Getting serialized report";
+ scoped_ptr<const 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_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(
+ contents(), resource, true);
+
+ // No call to FillCache
+
+ // The cache collection starts after the IPC from the DOM is fired.
+ ViewHostMsg_MalwareDOMDetails_Params params;
+ report->OnReceivedMalwareDOMDetails(params);
+
+ // Let the cache callbacks complete
+ MessageLoop::current()->RunAllPending();
+
+ LOG(INFO) << "Getting serialized report";
+ scoped_ptr<const 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