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

Side by Side Diff: chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc

Issue 42553002: Mostly integrate new malware IP blacklist with the csd client. When (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address more comments Created 7 years, 1 month 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/safe_browsing/browser_feature_extractor.h" 5 #include "chrome/browser/safe_browsing/browser_feature_extractor.h"
6 6
7 #include <map> 7 #include <map>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h" 12 #include "base/message_loop/message_loop.h"
13 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
14 #include "base/time/time.h" 14 #include "base/time/time.h"
15 #include "chrome/browser/history/history_backend.h" 15 #include "chrome/browser/history/history_backend.h"
16 #include "chrome/browser/history/history_service.h" 16 #include "chrome/browser/history/history_service.h"
17 #include "chrome/browser/history/history_service_factory.h" 17 #include "chrome/browser/history/history_service_factory.h"
18 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/safe_browsing/browser_features.h" 19 #include "chrome/browser/safe_browsing/browser_features.h"
20 #include "chrome/browser/safe_browsing/client_side_detection_service.h" 20 #include "chrome/browser/safe_browsing/client_side_detection_host.h"
21 #include "chrome/browser/safe_browsing/database_manager.h"
22 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
21 #include "chrome/browser/safe_browsing/ui_manager.h" 23 #include "chrome/browser/safe_browsing/ui_manager.h"
22 #include "chrome/common/safe_browsing/csd.pb.h" 24 #include "chrome/common/safe_browsing/csd.pb.h"
23 #include "chrome/test/base/chrome_render_view_host_test_harness.h" 25 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
24 #include "chrome/test/base/testing_profile.h" 26 #include "chrome/test/base/testing_profile.h"
25 #include "content/public/browser/navigation_controller.h" 27 #include "content/public/browser/navigation_controller.h"
26 #include "content/public/browser/web_contents.h" 28 #include "content/public/browser/web_contents.h"
27 #include "content/public/common/page_transition_types.h" 29 #include "content/public/common/page_transition_types.h"
28 #include "content/public/common/referrer.h" 30 #include "content/public/common/referrer.h"
29 #include "content/public/test/test_browser_thread.h" 31 #include "content/public/test/test_browser_thread.h"
30 #include "content/public/test/web_contents_tester.h" 32 #include "content/public/test/web_contents_tester.h"
31 #include "testing/gmock/include/gmock/gmock.h" 33 #include "testing/gmock/include/gmock/gmock.h"
32 #include "testing/gtest/include/gtest/gtest.h" 34 #include "testing/gtest/include/gtest/gtest.h"
33 #include "url/gurl.h" 35 #include "url/gurl.h"
34 36
37 using content::BrowserThread;
35 using content::WebContentsTester; 38 using content::WebContentsTester;
39
40 using testing::DoAll;
36 using testing::Return; 41 using testing::Return;
37 using testing::StrictMock; 42 using testing::StrictMock;
38 43
39 namespace safe_browsing { 44 namespace safe_browsing {
45
40 namespace { 46 namespace {
41 class MockClientSideDetectionService : public ClientSideDetectionService { 47
48 class MockSafeBrowsingDatabaseManager : public SafeBrowsingDatabaseManager {
42 public: 49 public:
43 MockClientSideDetectionService() : ClientSideDetectionService(NULL) {} 50 explicit MockSafeBrowsingDatabaseManager(
44 virtual ~MockClientSideDetectionService() {}; 51 scoped_refptr<SafeBrowsingService> service)
52 : SafeBrowsingDatabaseManager(service) { }
45 53
46 MOCK_CONST_METHOD1(IsBadIpAddress, bool(const std::string&)); 54 MOCK_METHOD1(MatchMalwareIP, bool(const std::string& ip_address));
55
56 protected:
57 virtual ~MockSafeBrowsingDatabaseManager() {}
58
59 private:
60 DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingDatabaseManager);
61 };
62
63 class MockClientSideDetectionHost : public ClientSideDetectionHost {
64 public:
65 MockClientSideDetectionHost(
66 content::WebContents* tab,
67 SafeBrowsingDatabaseManager* database_manager)
68 : ClientSideDetectionHost(tab) {
69 set_safe_browsing_managers(NULL, database_manager);
70 }
71
72 virtual ~MockClientSideDetectionHost() {};
73
74 MOCK_METHOD1(IsBadIpAddress, bool(const std::string&));
47 }; 75 };
48 } // namespace 76 } // namespace
49 77
50 class BrowserFeatureExtractorTest : public ChromeRenderViewHostTestHarness { 78 class BrowserFeatureExtractorTest : public ChromeRenderViewHostTestHarness {
51 protected: 79 protected:
52 virtual void SetUp() { 80 virtual void SetUp() {
53 ChromeRenderViewHostTestHarness::SetUp(); 81 ChromeRenderViewHostTestHarness::SetUp();
54 ASSERT_TRUE(profile()->CreateHistoryService( 82 ASSERT_TRUE(profile()->CreateHistoryService(
55 true /* delete_file */, false /* no_db */)); 83 true /* delete_file */, false /* no_db */));
56 service_.reset(new StrictMock<MockClientSideDetectionService>()); 84
85 sb_service_ = SafeBrowsingService::CreateSafeBrowsingService();
86 db_manager_ = new StrictMock<MockSafeBrowsingDatabaseManager>(
87 sb_service_);
88 host_.reset(new StrictMock<MockClientSideDetectionHost>(
89 web_contents(), db_manager_.get()));
57 extractor_.reset( 90 extractor_.reset(
58 new BrowserFeatureExtractor(web_contents(), service_.get())); 91 new BrowserFeatureExtractor(web_contents(), host_.get()));
59 num_pending_ = 0; 92 num_pending_ = 0;
60 browse_info_.reset(new BrowseInfo); 93 browse_info_.reset(new BrowseInfo);
61 } 94 }
62 95
63 virtual void TearDown() { 96 virtual void TearDown() {
97 browse_info_.reset();
64 extractor_.reset(); 98 extractor_.reset();
99 host_.reset();
mattm 2013/10/31 05:26:40 Are these reset()s necessary to release references
noé 2013/10/31 20:39:58 Fixed. I thought this was causing the sb_service_
65 profile()->DestroyHistoryService(); 100 profile()->DestroyHistoryService();
66 ChromeRenderViewHostTestHarness::TearDown(); 101 ChromeRenderViewHostTestHarness::TearDown();
67 ASSERT_EQ(0, num_pending_); 102 ASSERT_EQ(0, num_pending_);
68 } 103 }
69 104
70 HistoryService* history_service() { 105 HistoryService* history_service() {
71 return HistoryServiceFactory::GetForProfile(profile(), 106 return HistoryServiceFactory::GetForProfile(profile(),
72 Profile::EXPLICIT_ACCESS); 107 Profile::EXPLICIT_ACCESS);
73 } 108 }
74 109
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 std::map<std::string, double>* features) { 166 std::map<std::string, double>* features) {
132 for (int i = 0; i < request.non_model_feature_map_size(); ++i) { 167 for (int i = 0; i < request.non_model_feature_map_size(); ++i) {
133 const ClientPhishingRequest::Feature& feature = 168 const ClientPhishingRequest::Feature& feature =
134 request.non_model_feature_map(i); 169 request.non_model_feature_map(i);
135 EXPECT_EQ(0U, features->count(feature.name())); 170 EXPECT_EQ(0U, features->count(feature.name()));
136 (*features)[feature.name()] = feature.value(); 171 (*features)[feature.name()] = feature.value();
137 } 172 }
138 } 173 }
139 174
140 void ExtractMalwareFeatures(ClientMalwareRequest* request) { 175 void ExtractMalwareFeatures(ClientMalwareRequest* request) {
176 // Feature extraction takes ownership of the request object
177 // and passes it along to the done callback in the end.
178 StartExtractMalwareFeatures(request);
179 base::MessageLoopForUI::current()->Run();
180 EXPECT_EQ(1U, success_.count(request));
181 EXPECT_TRUE(success_[request]);
182 }
183
184 void StartExtractMalwareFeatures(ClientMalwareRequest* request) {
185 success_.erase(request);
186 ++num_pending_;
187 // We temporarily give up ownership of request to ExtractMalwareFeatures
188 // but we'll regain ownership of it in ExtractMalwareFeaturesDone.
141 extractor_->ExtractMalwareFeatures( 189 extractor_->ExtractMalwareFeatures(
142 browse_info_.get(), request); 190 browse_info_.get(),
191 request,
192 base::Bind(&BrowserFeatureExtractorTest::ExtractMalwareFeaturesDone,
193 base::Unretained(this)));
143 } 194 }
144 195
145 void GetMalwareFeatureMap( 196 void GetMalwareFeatureMap(
146 const ClientMalwareRequest& request, 197 const ClientMalwareRequest& request,
147 std::map<std::string, std::set<std::string> >* features) { 198 std::map<std::string, std::set<std::string> >* features) {
148 for (int i = 0; i < request.feature_map_size(); ++i) { 199 for (int i = 0; i < request.feature_map_size(); ++i) {
149 const ClientMalwareRequest::Feature& feature = 200 const ClientMalwareRequest::Feature& feature =
150 request.feature_map(i); 201 request.feature_map(i);
151 EXPECT_EQ(0U, features->count(feature.name())); 202 EXPECT_EQ(0U, features->count(feature.name()));
152 std::set<std::string> meta_infos; 203 std::set<std::string> meta_infos;
153 for (int j = 0; j < feature.metainfo_size(); ++j) { 204 for (int j = 0; j < feature.metainfo_size(); ++j) {
154 meta_infos.insert(feature.metainfo(j)); 205 meta_infos.insert(feature.metainfo(j));
155 } 206 }
156 (*features)[feature.name()] = meta_infos; 207 (*features)[feature.name()] = meta_infos;
157 } 208 }
158 } 209 }
159 210
160 int num_pending_; 211 int num_pending_; // Number of pending feature extractions.
161 scoped_ptr<BrowserFeatureExtractor> extractor_; 212 scoped_ptr<BrowserFeatureExtractor> extractor_;
162 std::map<ClientPhishingRequest*, bool> success_; 213 std::map<void*, bool> success_;
163 scoped_ptr<BrowseInfo> browse_info_; 214 scoped_ptr<BrowseInfo> browse_info_;
164 scoped_ptr<MockClientSideDetectionService> service_; 215 scoped_ptr<StrictMock<MockClientSideDetectionHost> > host_;
216 scoped_refptr<SafeBrowsingService> sb_service_;
217 scoped_refptr<StrictMock<MockSafeBrowsingDatabaseManager> > db_manager_;
165 218
166 private: 219 private:
167 void ExtractFeaturesDone(bool success, ClientPhishingRequest* request) { 220 void ExtractFeaturesDone(bool success, ClientPhishingRequest* request) {
168 ASSERT_EQ(0U, success_.count(request)); 221 ASSERT_EQ(0U, success_.count(request));
169 success_[request] = success; 222 success_[request] = success;
170 if (--num_pending_ == 0) { 223 if (--num_pending_ == 0) {
171 base::MessageLoop::current()->Quit(); 224 base::MessageLoop::current()->Quit();
172 } 225 }
173 } 226 }
227
228 void ExtractMalwareFeaturesDone(
229 bool success,
230 scoped_ptr<ClientMalwareRequest> request_copy) {
mattm 2013/10/31 05:26:40 not a copy anymore
noé 2013/10/31 20:39:58 Done.
231 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
232 ASSERT_EQ(0U, success_.count(request_copy.get()));
233 // The pointer doesn't really belong to us. It belongs to
234 // the test case which passed it to ExtractMalwareFeatures above.
235 success_[request_copy.release()] = success;
236 if (--num_pending_ == 0) {
237 base::MessageLoopForUI::current()->Quit();
238 }
239 }
174 }; 240 };
175 241
176 TEST_F(BrowserFeatureExtractorTest, UrlNotInHistory) { 242 TEST_F(BrowserFeatureExtractorTest, UrlNotInHistory) {
177 ClientPhishingRequest request; 243 ClientPhishingRequest request;
178 SimpleNavigateAndCommit(GURL("http://www.google.com")); 244 SimpleNavigateAndCommit(GURL("http://www.google.com"));
179 request.set_url("http://www.google.com/"); 245 request.set_url("http://www.google.com/");
180 request.set_client_score(0.5); 246 request.set_client_score(0.5);
181 EXPECT_FALSE(ExtractFeatures(&request)); 247 EXPECT_FALSE(ExtractFeatures(&request));
182 } 248 }
183 249
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 request.set_url("http://www.baz.com/"); 539 request.set_url("http://www.baz.com/");
474 request.set_client_score(0.5); 540 request.set_client_score(0.5);
475 redirect_chain.clear(); 541 redirect_chain.clear();
476 redirect_chain.push_back(GURL("https://bankofamerica.com")); 542 redirect_chain.push_back(GURL("https://bankofamerica.com"));
477 redirect_chain.push_back(GURL("http://www.baz.com/")); 543 redirect_chain.push_back(GURL("http://www.baz.com/"));
478 SetRedirectChain(redirect_chain, true); 544 SetRedirectChain(redirect_chain, true);
479 NavigateAndCommit(GURL("http://www.baz.com"), 545 NavigateAndCommit(GURL("http://www.baz.com"),
480 GURL("https://bankofamerica.com"), 546 GURL("https://bankofamerica.com"),
481 content::PAGE_TRANSITION_GENERATED); 547 content::PAGE_TRANSITION_GENERATED);
482 548
483 std::set<std::string> urls;
484 urls.insert("http://test.com");
485 browse_info_->ips.insert(std::make_pair("193.5.163.8", urls));
486 browse_info_->ips.insert(std::make_pair("23.94.78.1", urls));
487 EXPECT_CALL(*service_, IsBadIpAddress("193.5.163.8")).WillOnce(Return(true));
488 EXPECT_CALL(*service_, IsBadIpAddress("23.94.78.1")).WillOnce(Return(false));
489
490 EXPECT_TRUE(ExtractFeatures(&request)); 549 EXPECT_TRUE(ExtractFeatures(&request));
491 features.clear(); 550 features.clear();
492 GetFeatureMap(request, &features); 551 GetFeatureMap(request, &features);
493 552
494 EXPECT_EQ(1.0, 553 EXPECT_EQ(1.0,
495 features[base::StringPrintf("%s[0]=%s", 554 features[base::StringPrintf("%s[0]=%s",
496 features::kRedirect, 555 features::kRedirect,
497 features::kSecureRedirectValue)]); 556 features::kSecureRedirectValue)]);
498 EXPECT_EQ(1.0, features[features::kHasSSLReferrer]); 557 EXPECT_EQ(1.0, features[features::kHasSSLReferrer]);
499 EXPECT_EQ(5.0, features[features::kPageTransitionType]); 558 EXPECT_EQ(5.0, features[features::kPageTransitionType]);
500 // Should not have redirect or host features. 559 // Should not have redirect or host features.
501 EXPECT_EQ(0U, 560 EXPECT_EQ(0U,
502 features.count(base::StringPrintf("%s%s", 561 features.count(base::StringPrintf("%s%s",
503 features::kHostPrefix, 562 features::kHostPrefix,
504 features::kPageTransitionType))); 563 features::kPageTransitionType)));
505 EXPECT_EQ(0U, 564 EXPECT_EQ(0U,
506 features.count(base::StringPrintf("%s%s", 565 features.count(base::StringPrintf("%s%s",
507 features::kHostPrefix, 566 features::kHostPrefix,
508 features::kIsFirstNavigation))); 567 features::kIsFirstNavigation)));
509 EXPECT_EQ(5.0, features[features::kPageTransitionType]); 568 EXPECT_EQ(5.0, features[features::kPageTransitionType]);
510 EXPECT_EQ(1.0, features[std::string(features::kBadIpFetch) + "193.5.163.8"]);
511 EXPECT_FALSE(features.count(std::string(features::kBadIpFetch) +
512 "23.94.78.1"));
513 } 569 }
514 570
515 TEST_F(BrowserFeatureExtractorTest, SafeBrowsingFeatures) { 571 TEST_F(BrowserFeatureExtractorTest, SafeBrowsingFeatures) {
516 SimpleNavigateAndCommit(GURL("http://www.foo.com/malware.html")); 572 SimpleNavigateAndCommit(GURL("http://www.foo.com/malware.html"));
517 ClientPhishingRequest request; 573 ClientPhishingRequest request;
518 request.set_url("http://www.foo.com/malware.html"); 574 request.set_url("http://www.foo.com/malware.html");
519 request.set_client_score(0.5); 575 request.set_client_score(0.5);
520 576
521 browse_info_->unsafe_resource.reset( 577 browse_info_->unsafe_resource.reset(
522 new SafeBrowsingUIManager::UnsafeResource); 578 new SafeBrowsingUIManager::UnsafeResource);
(...skipping 22 matching lines...) Expand all
545 request.set_url("http://www.foo.com/"); 601 request.set_url("http://www.foo.com/");
546 602
547 std::set<std::string> bad_urls; 603 std::set<std::string> bad_urls;
548 bad_urls.insert("http://bad.com"); 604 bad_urls.insert("http://bad.com");
549 bad_urls.insert("http://evil.com"); 605 bad_urls.insert("http://evil.com");
550 browse_info_->ips.insert(std::make_pair("193.5.163.8", bad_urls)); 606 browse_info_->ips.insert(std::make_pair("193.5.163.8", bad_urls));
551 browse_info_->ips.insert(std::make_pair("92.92.92.92", bad_urls)); 607 browse_info_->ips.insert(std::make_pair("92.92.92.92", bad_urls));
552 std::set<std::string> good_urls; 608 std::set<std::string> good_urls;
553 good_urls.insert("http://ok.com"); 609 good_urls.insert("http://ok.com");
554 browse_info_->ips.insert(std::make_pair("23.94.78.1", good_urls)); 610 browse_info_->ips.insert(std::make_pair("23.94.78.1", good_urls));
555 EXPECT_CALL(*service_, IsBadIpAddress("193.5.163.8")).WillOnce(Return(true)); 611 EXPECT_CALL(*db_manager_, MatchMalwareIP("193.5.163.8"))
556 EXPECT_CALL(*service_, IsBadIpAddress("92.92.92.92")).WillOnce(Return(true)); 612 .WillOnce(Return(true));
557 EXPECT_CALL(*service_, IsBadIpAddress("23.94.78.1")).WillOnce(Return(false)); 613 EXPECT_CALL(*db_manager_, MatchMalwareIP("92.92.92.92"))
614 .WillOnce(Return(true));
615 EXPECT_CALL(*db_manager_, MatchMalwareIP("23.94.78.1"))
616 .WillOnce(Return(false));
558 617
559 ExtractMalwareFeatures(&request); 618 ExtractMalwareFeatures(&request);
560 std::map<std::string, std::set<std::string> > features; 619 std::map<std::string, std::set<std::string> > features;
561 GetMalwareFeatureMap(request, &features); 620 GetMalwareFeatureMap(request, &features);
562 621
563 EXPECT_EQ(2U, features.size()); 622 EXPECT_EQ(2U, features.size());
564 std::string feature_name = base::StringPrintf("%s%s", features::kBadIpFetch, 623 std::string feature_name = base::StringPrintf("%s%s", features::kBadIpFetch,
565 "193.5.163.8"); 624 "193.5.163.8");
566 EXPECT_TRUE(features.count(feature_name)); 625 EXPECT_TRUE(features.count(feature_name));
567 std::set<std::string> urls = features[feature_name]; 626 std::set<std::string> urls = features[feature_name];
(...skipping 13 matching lines...) Expand all
581 ClientMalwareRequest request; 640 ClientMalwareRequest request;
582 request.set_url("http://www.foo.com/"); 641 request.set_url("http://www.foo.com/");
583 642
584 std::set<std::string> bad_urls; 643 std::set<std::string> bad_urls;
585 bad_urls.insert("http://bad.com"); 644 bad_urls.insert("http://bad.com");
586 std::vector<std::string> ips; 645 std::vector<std::string> ips;
587 for (int i = 0; i < 7; ++i) { // Add 7 ips 646 for (int i = 0; i < 7; ++i) { // Add 7 ips
588 std::string ip = base::StringPrintf("%d.%d.%d.%d", i, i, i, i); 647 std::string ip = base::StringPrintf("%d.%d.%d.%d", i, i, i, i);
589 ips.push_back(ip); 648 ips.push_back(ip);
590 browse_info_->ips.insert(std::make_pair(ip, bad_urls)); 649 browse_info_->ips.insert(std::make_pair(ip, bad_urls));
591 }
592 650
593 // First ip is good, then check the next 5 bad ips. 651 // First ip is good but all the others are bad.
594 // Not check the 7th as reached limit. 652 EXPECT_CALL(*db_manager_, MatchMalwareIP(ip)).WillOnce(Return(i > 0));
595 EXPECT_CALL(*service_, IsBadIpAddress(ips[0])).WillOnce(Return(false));
596 for (int i = 1; i < 6; ++i) {
597 EXPECT_CALL(*service_, IsBadIpAddress(ips[i])).WillOnce(Return(true));
598 } 653 }
599 654
600 ExtractMalwareFeatures(&request); 655 ExtractMalwareFeatures(&request);
601 std::map<std::string, std::set<std::string> > features; 656 std::map<std::string, std::set<std::string> > features;
602 GetMalwareFeatureMap(request, &features); 657 GetMalwareFeatureMap(request, &features);
603 658
604 // Only keep 5 ips. 659 // The number of IP match features we store is capped at 5 IPs per request.
605 EXPECT_EQ(5U, features.size()); 660 EXPECT_EQ(5U, features.size());
606 } 661 }
607 662
608 } // namespace safe_browsing 663 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698