| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "base/file_path.h" | 5 #include "base/file_path.h" |
| 6 #include "base/memory/ref_counted.h" | 6 #include "base/memory/ref_counted.h" |
| 7 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
| 8 #include "base/task.h" | 8 #include "base/task.h" |
| 9 #include "chrome/browser/safe_browsing/browser_feature_extractor.h" | 9 #include "chrome/browser/safe_browsing/browser_feature_extractor.h" |
| 10 #include "chrome/browser/safe_browsing/client_side_detection_host.h" | 10 #include "chrome/browser/safe_browsing/client_side_detection_host.h" |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 using ::testing::SetArgumentPointee; | 38 using ::testing::SetArgumentPointee; |
| 39 using ::testing::StrictMock; | 39 using ::testing::StrictMock; |
| 40 | 40 |
| 41 namespace { | 41 namespace { |
| 42 const bool kFalse = false; | 42 const bool kFalse = false; |
| 43 const bool kTrue = true; | 43 const bool kTrue = true; |
| 44 } | 44 } |
| 45 | 45 |
| 46 namespace safe_browsing { | 46 namespace safe_browsing { |
| 47 namespace { | 47 namespace { |
| 48 MATCHER_P(EqualsProto, other, "") { | 48 // This matcher verifies that the client computed verdict |
| 49 return other.SerializeAsString() == arg.SerializeAsString(); | 49 // (ClientPhishingRequest) which is passed to SendClientReportPhishingRequest |
| 50 // has the expected fields set. Note: we can't simply compare the protocol |
| 51 // buffer strings because the BrowserFeatureExtractor might add features to the |
| 52 // verdict object before calling SendClientReportPhishingRequest. |
| 53 MATCHER_P(PartiallyEqualVerdict, other, "") { |
| 54 return (other.url() == arg.url() && |
| 55 other.client_score() == arg.client_score() && |
| 56 other.is_phishing() == arg.is_phishing()); |
| 50 } | 57 } |
| 51 | 58 |
| 52 ACTION(QuitUIMessageLoop) { | 59 ACTION(QuitUIMessageLoop) { |
| 53 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 60 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 54 MessageLoopForUI::current()->Quit(); | 61 MessageLoopForUI::current()->Quit(); |
| 55 } | 62 } |
| 56 | 63 |
| 57 class MockClientSideDetectionService : public ClientSideDetectionService { | 64 class MockClientSideDetectionService : public ClientSideDetectionService { |
| 58 public: | 65 public: |
| 59 MockClientSideDetectionService() : ClientSideDetectionService(NULL) {} | 66 MockClientSideDetectionService() : ClientSideDetectionService(NULL) {} |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 | 107 |
| 101 MOCK_METHOD0(IsOffTheRecord, bool()); | 108 MOCK_METHOD0(IsOffTheRecord, bool()); |
| 102 }; | 109 }; |
| 103 | 110 |
| 104 class MockBrowserFeatureExtractor : public BrowserFeatureExtractor { | 111 class MockBrowserFeatureExtractor : public BrowserFeatureExtractor { |
| 105 public: | 112 public: |
| 106 explicit MockBrowserFeatureExtractor(TabContents* tab) | 113 explicit MockBrowserFeatureExtractor(TabContents* tab) |
| 107 : BrowserFeatureExtractor(tab) {} | 114 : BrowserFeatureExtractor(tab) {} |
| 108 virtual ~MockBrowserFeatureExtractor() {} | 115 virtual ~MockBrowserFeatureExtractor() {} |
| 109 | 116 |
| 110 MOCK_METHOD2(ExtractFeatures, void(ClientPhishingRequest*, | 117 MOCK_METHOD3(ExtractFeatures, void(const BrowseInfo& info, |
| 118 ClientPhishingRequest*, |
| 111 BrowserFeatureExtractor::DoneCallback*)); | 119 BrowserFeatureExtractor::DoneCallback*)); |
| 112 }; | 120 }; |
| 113 | 121 |
| 114 // Helper function which quits the UI message loop from the IO message loop. | 122 // Helper function which quits the UI message loop from the IO message loop. |
| 115 void QuitUIMessageLoopFromIO() { | 123 void QuitUIMessageLoopFromIO() { |
| 116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 124 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 117 BrowserThread::PostTask(BrowserThread::UI, | 125 BrowserThread::PostTask(BrowserThread::UI, |
| 118 FROM_HERE, | 126 FROM_HERE, |
| 119 new MessageLoop::QuitTask()); | 127 new MessageLoop::QuitTask()); |
| 120 } | 128 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 144 csd_host_->set_safe_browsing_service(sb_service_.get()); | 152 csd_host_->set_safe_browsing_service(sb_service_.get()); |
| 145 } | 153 } |
| 146 | 154 |
| 147 virtual void TearDown() { | 155 virtual void TearDown() { |
| 148 io_thread_.reset(); | 156 io_thread_.reset(); |
| 149 ui_thread_.reset(); | 157 ui_thread_.reset(); |
| 150 TabContentsWrapperTestHarness::TearDown(); | 158 TabContentsWrapperTestHarness::TearDown(); |
| 151 } | 159 } |
| 152 | 160 |
| 153 void OnDetectedPhishingSite(const std::string& verdict_str) { | 161 void OnDetectedPhishingSite(const std::string& verdict_str) { |
| 162 // Make sure we have a valid BrowseInfo object set before we call this |
| 163 // method. |
| 164 csd_host_->browse_info_.reset(new BrowseInfo); |
| 154 csd_host_->OnDetectedPhishingSite(verdict_str); | 165 csd_host_->OnDetectedPhishingSite(verdict_str); |
| 155 } | 166 } |
| 156 | 167 |
| 157 void FlushIOMessageLoop() { | 168 void FlushIOMessageLoop() { |
| 158 // If there was a message posted on the IO thread to display the | 169 // If there was a message posted on the IO thread to display the |
| 159 // interstitial page we know that it would have been posted before | 170 // interstitial page we know that it would have been posted before |
| 160 // we put the quit message there. | 171 // we put the quit message there. |
| 161 BrowserThread::PostTask(BrowserThread::IO, | 172 BrowserThread::PostTask(BrowserThread::IO, |
| 162 FROM_HERE, | 173 FROM_HERE, |
| 163 NewRunnableFunction(&QuitUIMessageLoopFromIO)); | 174 NewRunnableFunction(&QuitUIMessageLoopFromIO)); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 scoped_ptr<BrowserThread> ui_thread_; | 232 scoped_ptr<BrowserThread> ui_thread_; |
| 222 scoped_ptr<BrowserThread> io_thread_; | 233 scoped_ptr<BrowserThread> io_thread_; |
| 223 }; | 234 }; |
| 224 | 235 |
| 225 TEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteInvalidVerdict) { | 236 TEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteInvalidVerdict) { |
| 226 // Case 0: renderer sends an invalid verdict string that we're unable to | 237 // Case 0: renderer sends an invalid verdict string that we're unable to |
| 227 // parse. | 238 // parse. |
| 228 MockBrowserFeatureExtractor* mock_extractor = new MockBrowserFeatureExtractor( | 239 MockBrowserFeatureExtractor* mock_extractor = new MockBrowserFeatureExtractor( |
| 229 contents()); | 240 contents()); |
| 230 SetFeatureExtractor(mock_extractor); // The host class takes ownership. | 241 SetFeatureExtractor(mock_extractor); // The host class takes ownership. |
| 231 EXPECT_CALL(*mock_extractor, ExtractFeatures(_, _)).Times(0); | 242 EXPECT_CALL(*mock_extractor, ExtractFeatures(_, _, _)).Times(0); |
| 232 OnDetectedPhishingSite("Invalid Protocol Buffer"); | 243 OnDetectedPhishingSite("Invalid Protocol Buffer"); |
| 233 EXPECT_TRUE(Mock::VerifyAndClear(mock_extractor)); | 244 EXPECT_TRUE(Mock::VerifyAndClear(mock_extractor)); |
| 234 } | 245 } |
| 235 | 246 |
| 236 TEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteNotPhishing) { | 247 TEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteNotPhishing) { |
| 237 // Case 1: client thinks the page is phishing. The server does not agree. | 248 // Case 1: client thinks the page is phishing. The server does not agree. |
| 238 // No interstitial is shown. | 249 // No interstitial is shown. |
| 239 ClientSideDetectionService::ClientReportPhishingRequestCallback* cb; | 250 ClientSideDetectionService::ClientReportPhishingRequestCallback* cb; |
| 240 ClientPhishingRequest verdict; | 251 ClientPhishingRequest verdict; |
| 241 verdict.set_url("http://phishingurl.com/"); | 252 verdict.set_url("http://phishingurl.com/"); |
| 242 verdict.set_client_score(1.0f); | 253 verdict.set_client_score(1.0f); |
| 243 verdict.set_is_phishing(true); | 254 verdict.set_is_phishing(true); |
| 244 | 255 |
| 245 EXPECT_CALL(*csd_service_, | 256 EXPECT_CALL(*csd_service_, |
| 246 SendClientReportPhishingRequest(Pointee(EqualsProto(verdict)), _)) | 257 SendClientReportPhishingRequest( |
| 258 Pointee(PartiallyEqualVerdict(verdict)), _)) |
| 247 .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb), QuitUIMessageLoop())); | 259 .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb), QuitUIMessageLoop())); |
| 248 OnDetectedPhishingSite(verdict.SerializeAsString()); | 260 OnDetectedPhishingSite(verdict.SerializeAsString()); |
| 249 MessageLoop::current()->Run(); | 261 MessageLoop::current()->Run(); |
| 250 EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get())); | 262 EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get())); |
| 251 ASSERT_TRUE(cb); | 263 ASSERT_TRUE(cb); |
| 252 | 264 |
| 253 // Make sure DoDisplayBlockingPage is not going to be called. | 265 // Make sure DoDisplayBlockingPage is not going to be called. |
| 254 EXPECT_CALL(*sb_service_, DoDisplayBlockingPage(_)).Times(0); | 266 EXPECT_CALL(*sb_service_, DoDisplayBlockingPage(_)).Times(0); |
| 255 cb->Run(GURL(verdict.url()), false); | 267 cb->Run(GURL(verdict.url()), false); |
| 256 delete cb; | 268 delete cb; |
| 257 MessageLoop::current()->RunAllPending(); | 269 MessageLoop::current()->RunAllPending(); |
| 258 EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get())); | 270 EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get())); |
| 259 } | 271 } |
| 260 | 272 |
| 261 TEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteDisabled) { | 273 TEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteDisabled) { |
| 262 // Case 2: client thinks the page is phishing and so does the server but | 274 // Case 2: client thinks the page is phishing and so does the server but |
| 263 // showing the interstitial is disabled => no interstitial is shown. | 275 // showing the interstitial is disabled => no interstitial is shown. |
| 264 ClientSideDetectionService::ClientReportPhishingRequestCallback* cb; | 276 ClientSideDetectionService::ClientReportPhishingRequestCallback* cb; |
| 265 ClientPhishingRequest verdict; | 277 ClientPhishingRequest verdict; |
| 266 verdict.set_url("http://phishingurl.com/"); | 278 verdict.set_url("http://phishingurl.com/"); |
| 267 verdict.set_client_score(1.0f); | 279 verdict.set_client_score(1.0f); |
| 268 verdict.set_is_phishing(true); | 280 verdict.set_is_phishing(true); |
| 269 | 281 |
| 270 EXPECT_CALL(*csd_service_, | 282 EXPECT_CALL(*csd_service_, |
| 271 SendClientReportPhishingRequest(Pointee(EqualsProto(verdict)), _)) | 283 SendClientReportPhishingRequest( |
| 284 Pointee(PartiallyEqualVerdict(verdict)), _)) |
| 272 .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb), QuitUIMessageLoop())); | 285 .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb), QuitUIMessageLoop())); |
| 273 OnDetectedPhishingSite(verdict.SerializeAsString()); | 286 OnDetectedPhishingSite(verdict.SerializeAsString()); |
| 274 MessageLoop::current()->Run(); | 287 MessageLoop::current()->Run(); |
| 275 EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get())); | 288 EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get())); |
| 276 ASSERT_TRUE(cb); | 289 ASSERT_TRUE(cb); |
| 277 | 290 |
| 278 // Make sure DoDisplayBlockingPage is not going to be called. | 291 // Make sure DoDisplayBlockingPage is not going to be called. |
| 279 EXPECT_CALL(*sb_service_, DoDisplayBlockingPage(_)).Times(0); | 292 EXPECT_CALL(*sb_service_, DoDisplayBlockingPage(_)).Times(0); |
| 280 cb->Run(GURL(verdict.url()), false); | 293 cb->Run(GURL(verdict.url()), false); |
| 281 delete cb; | 294 delete cb; |
| 282 MessageLoop::current()->RunAllPending(); | 295 MessageLoop::current()->RunAllPending(); |
| 283 EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get())); | 296 EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get())); |
| 284 } | 297 } |
| 285 | 298 |
| 286 TEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteShowInterstitial) { | 299 TEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteShowInterstitial) { |
| 287 // Case 3: client thinks the page is phishing and so does the server. | 300 // Case 3: client thinks the page is phishing and so does the server. |
| 288 // We show an interstitial. | 301 // We show an interstitial. |
| 289 ClientSideDetectionService::ClientReportPhishingRequestCallback* cb; | 302 ClientSideDetectionService::ClientReportPhishingRequestCallback* cb; |
| 290 GURL phishing_url("http://phishingurl.com/"); | 303 GURL phishing_url("http://phishingurl.com/"); |
| 291 ClientPhishingRequest verdict; | 304 ClientPhishingRequest verdict; |
| 292 verdict.set_url(phishing_url.spec()); | 305 verdict.set_url(phishing_url.spec()); |
| 293 verdict.set_client_score(1.0f); | 306 verdict.set_client_score(1.0f); |
| 294 verdict.set_is_phishing(true); | 307 verdict.set_is_phishing(true); |
| 295 | 308 |
| 296 EXPECT_CALL(*csd_service_, | 309 EXPECT_CALL(*csd_service_, |
| 297 SendClientReportPhishingRequest(Pointee(EqualsProto(verdict)), _)) | 310 SendClientReportPhishingRequest( |
| 311 Pointee(PartiallyEqualVerdict(verdict)), _)) |
| 298 .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb), QuitUIMessageLoop())); | 312 .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb), QuitUIMessageLoop())); |
| 299 OnDetectedPhishingSite(verdict.SerializeAsString()); | 313 OnDetectedPhishingSite(verdict.SerializeAsString()); |
| 300 MessageLoop::current()->Run(); | 314 MessageLoop::current()->Run(); |
| 301 EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get())); | 315 EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get())); |
| 302 ASSERT_TRUE(cb); | 316 ASSERT_TRUE(cb); |
| 303 | 317 |
| 304 SafeBrowsingService::UnsafeResource resource; | 318 SafeBrowsingService::UnsafeResource resource; |
| 305 EXPECT_CALL(*sb_service_, DoDisplayBlockingPage(_)) | 319 EXPECT_CALL(*sb_service_, DoDisplayBlockingPage(_)) |
| 306 .WillOnce(SaveArg<0>(&resource)); | 320 .WillOnce(SaveArg<0>(&resource)); |
| 307 cb->Run(phishing_url, true); | 321 cb->Run(phishing_url, true); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 // server responds for both requests with a phishing verdict. Only | 354 // server responds for both requests with a phishing verdict. Only |
| 341 // a single interstitial is shown for the second URL. | 355 // a single interstitial is shown for the second URL. |
| 342 ClientSideDetectionService::ClientReportPhishingRequestCallback* cb; | 356 ClientSideDetectionService::ClientReportPhishingRequestCallback* cb; |
| 343 GURL phishing_url("http://phishingurl.com/"); | 357 GURL phishing_url("http://phishingurl.com/"); |
| 344 ClientPhishingRequest verdict; | 358 ClientPhishingRequest verdict; |
| 345 verdict.set_url(phishing_url.spec()); | 359 verdict.set_url(phishing_url.spec()); |
| 346 verdict.set_client_score(1.0f); | 360 verdict.set_client_score(1.0f); |
| 347 verdict.set_is_phishing(true); | 361 verdict.set_is_phishing(true); |
| 348 | 362 |
| 349 EXPECT_CALL(*csd_service_, | 363 EXPECT_CALL(*csd_service_, |
| 350 SendClientReportPhishingRequest(Pointee(EqualsProto(verdict)), _)) | 364 SendClientReportPhishingRequest( |
| 365 Pointee(PartiallyEqualVerdict(verdict)), _)) |
| 351 .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb), QuitUIMessageLoop())); | 366 .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb), QuitUIMessageLoop())); |
| 352 OnDetectedPhishingSite(verdict.SerializeAsString()); | 367 OnDetectedPhishingSite(verdict.SerializeAsString()); |
| 353 MessageLoop::current()->Run(); | 368 MessageLoop::current()->Run(); |
| 354 EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get())); | 369 EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get())); |
| 355 ASSERT_TRUE(cb); | 370 ASSERT_TRUE(cb); |
| 356 GURL other_phishing_url("http://other_phishing_url.com/bla"); | 371 GURL other_phishing_url("http://other_phishing_url.com/bla"); |
| 357 ExpectPreClassificationChecks(other_phishing_url, &kFalse, &kFalse, &kFalse, | 372 ExpectPreClassificationChecks(other_phishing_url, &kFalse, &kFalse, &kFalse, |
| 358 &kFalse, &kFalse, &kFalse); | 373 &kFalse, &kFalse, &kFalse); |
| 359 // We navigate away. The callback cb should be revoked. | 374 // We navigate away. The callback cb should be revoked. |
| 360 NavigateAndCommit(other_phishing_url); | 375 NavigateAndCommit(other_phishing_url); |
| 361 // Wait for the pre-classification checks to finish for other_phishing_url. | 376 // Wait for the pre-classification checks to finish for other_phishing_url. |
| 362 WaitAndCheckPreClassificationChecks(); | 377 WaitAndCheckPreClassificationChecks(); |
| 363 | 378 |
| 364 ClientSideDetectionService::ClientReportPhishingRequestCallback* cb_other; | 379 ClientSideDetectionService::ClientReportPhishingRequestCallback* cb_other; |
| 365 verdict.set_url(other_phishing_url.spec()); | 380 verdict.set_url(other_phishing_url.spec()); |
| 366 verdict.set_client_score(0.8f); | 381 verdict.set_client_score(0.8f); |
| 367 EXPECT_CALL(*csd_service_, | 382 EXPECT_CALL(*csd_service_, |
| 368 SendClientReportPhishingRequest(Pointee(EqualsProto(verdict)), _)) | 383 SendClientReportPhishingRequest( |
| 384 Pointee(PartiallyEqualVerdict(verdict)), _)) |
| 369 .WillOnce(DoAll(DeleteArg<0>(), | 385 .WillOnce(DoAll(DeleteArg<0>(), |
| 370 SaveArg<1>(&cb_other), | 386 SaveArg<1>(&cb_other), |
| 371 QuitUIMessageLoop())); | 387 QuitUIMessageLoop())); |
| 372 OnDetectedPhishingSite(verdict.SerializeAsString()); | 388 OnDetectedPhishingSite(verdict.SerializeAsString()); |
| 373 MessageLoop::current()->Run(); | 389 MessageLoop::current()->Run(); |
| 374 EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get())); | 390 EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get())); |
| 375 ASSERT_TRUE(cb_other); | 391 ASSERT_TRUE(cb_other); |
| 376 | 392 |
| 377 // We expect that the interstitial is shown for the second phishing URL and | 393 // We expect that the interstitial is shown for the second phishing URL and |
| 378 // not for the first phishing URL. | 394 // not for the first phishing URL. |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get())); | 608 EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get())); |
| 593 EXPECT_EQ(url, resource.url); | 609 EXPECT_EQ(url, resource.url); |
| 594 EXPECT_EQ(url, resource.original_url); | 610 EXPECT_EQ(url, resource.original_url); |
| 595 delete resource.client; | 611 delete resource.client; |
| 596 msg = process()->sink().GetFirstMessageMatching( | 612 msg = process()->sink().GetFirstMessageMatching( |
| 597 SafeBrowsingMsg_StartPhishingDetection::ID); | 613 SafeBrowsingMsg_StartPhishingDetection::ID); |
| 598 ASSERT_FALSE(msg); | 614 ASSERT_FALSE(msg); |
| 599 } | 615 } |
| 600 | 616 |
| 601 } // namespace safe_browsing | 617 } // namespace safe_browsing |
| OLD | NEW |