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 // Note that although this is not a "browser" test, it runs as part of | 5 // Note that although this is not a "browser" test, it runs as part of |
6 // browser_tests. This is because WebKit does not work properly if it is | 6 // browser_tests. This is because WebKit does not work properly if it is |
7 // shutdown and re-initialized. Since browser_tests runs each test in a | 7 // shutdown and re-initialized. Since browser_tests runs each test in a |
8 // new process, this avoids the problem. | 8 // new process, this avoids the problem. |
9 | 9 |
10 #include "chrome/renderer/safe_browsing/phishing_dom_feature_extractor.h" | 10 #include "chrome/renderer/safe_browsing/phishing_dom_feature_extractor.h" |
11 | 11 |
| 12 #include "base/bind.h" |
12 #include "base/callback.h" | 13 #include "base/callback.h" |
| 14 #include "base/compiler_specific.h" |
| 15 #include "base/memory/weak_ptr.h" |
13 #include "base/message_loop.h" | 16 #include "base/message_loop.h" |
14 #include "base/time.h" | 17 #include "base/time.h" |
15 #include "chrome/renderer/safe_browsing/features.h" | 18 #include "chrome/renderer/safe_browsing/features.h" |
16 #include "chrome/renderer/safe_browsing/mock_feature_extractor_clock.h" | 19 #include "chrome/renderer/safe_browsing/mock_feature_extractor_clock.h" |
17 #include "chrome/renderer/safe_browsing/render_view_fake_resources_test.h" | 20 #include "chrome/renderer/safe_browsing/render_view_fake_resources_test.h" |
18 #include "testing/gmock/include/gmock/gmock.h" | 21 #include "testing/gmock/include/gmock/gmock.h" |
| 22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
| 23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h" |
| 24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" |
19 | 25 |
20 using ::testing::ContainerEq; | 26 using ::testing::ContainerEq; |
| 27 using ::testing::DoAll; |
| 28 using ::testing::Invoke; |
21 using ::testing::Return; | 29 using ::testing::Return; |
22 | 30 |
23 namespace safe_browsing { | 31 namespace safe_browsing { |
24 | 32 |
25 class PhishingDOMFeatureExtractorTest : public RenderViewFakeResourcesTest { | 33 class PhishingDOMFeatureExtractorTest : public RenderViewFakeResourcesTest { |
| 34 public: |
| 35 // Helper for the SubframeRemoval test that posts a message to remove |
| 36 // the iframe "frame1" from the document. |
| 37 void ScheduleRemoveIframe() { |
| 38 message_loop_.PostTask( |
| 39 FROM_HERE, |
| 40 base::Bind(&PhishingDOMFeatureExtractorTest::RemoveIframe, |
| 41 weak_factory_.GetWeakPtr())); |
| 42 } |
| 43 |
26 protected: | 44 protected: |
| 45 PhishingDOMFeatureExtractorTest() |
| 46 : RenderViewFakeResourcesTest(), |
| 47 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {} |
| 48 |
| 49 virtual ~PhishingDOMFeatureExtractorTest() {} |
| 50 |
27 virtual void SetUp() { | 51 virtual void SetUp() { |
28 // Set up WebKit and the RenderView. | 52 // Set up WebKit and the RenderView. |
29 RenderViewFakeResourcesTest::SetUp(); | 53 RenderViewFakeResourcesTest::SetUp(); |
30 extractor_.reset(new PhishingDOMFeatureExtractor(view_, &clock_)); | 54 extractor_.reset(new PhishingDOMFeatureExtractor(view_, &clock_)); |
31 } | 55 } |
32 | 56 |
33 virtual void TearDown() { | 57 virtual void TearDown() { |
34 RenderViewFakeResourcesTest::TearDown(); | 58 RenderViewFakeResourcesTest::TearDown(); |
35 } | 59 } |
36 | 60 |
37 // Runs the DOMFeatureExtractor on the RenderView, waiting for the | 61 // Runs the DOMFeatureExtractor on the RenderView, waiting for the |
38 // completion callback. Returns the success boolean from the callback. | 62 // completion callback. Returns the success boolean from the callback. |
39 bool ExtractFeatures(FeatureMap* features) { | 63 bool ExtractFeatures(FeatureMap* features) { |
40 success_ = false; | 64 success_ = false; |
41 extractor_->ExtractFeatures( | 65 extractor_->ExtractFeatures( |
42 features, | 66 features, |
43 NewCallback(this, &PhishingDOMFeatureExtractorTest::ExtractionDone)); | 67 NewCallback(this, &PhishingDOMFeatureExtractorTest::ExtractionDone)); |
44 message_loop_.Run(); | 68 message_loop_.Run(); |
45 return success_; | 69 return success_; |
46 } | 70 } |
47 | 71 |
48 // Completion callback for feature extraction. | 72 // Completion callback for feature extraction. |
49 void ExtractionDone(bool success) { | 73 void ExtractionDone(bool success) { |
50 success_ = success; | 74 success_ = success; |
51 message_loop_.Quit(); | 75 message_loop_.Quit(); |
52 } | 76 } |
53 | 77 |
| 78 // Does the actual work of removing the iframe "frame1" from the document. |
| 79 void RemoveIframe() { |
| 80 WebKit::WebFrame* main_frame = GetMainFrame(); |
| 81 ASSERT_TRUE(main_frame); |
| 82 main_frame->executeScript( |
| 83 WebKit::WebString( |
| 84 "document.body.removeChild(document.getElementById('frame1'));")); |
| 85 } |
| 86 |
54 MockFeatureExtractorClock clock_; | 87 MockFeatureExtractorClock clock_; |
55 scoped_ptr<PhishingDOMFeatureExtractor> extractor_; | 88 scoped_ptr<PhishingDOMFeatureExtractor> extractor_; |
56 bool success_; // holds the success value from ExtractFeatures | 89 bool success_; // holds the success value from ExtractFeatures |
| 90 base::WeakPtrFactory<PhishingDOMFeatureExtractorTest> weak_factory_; |
57 }; | 91 }; |
58 | 92 |
59 TEST_F(PhishingDOMFeatureExtractorTest, FormFeatures) { | 93 TEST_F(PhishingDOMFeatureExtractorTest, FormFeatures) { |
60 // This test doesn't exercise the extraction timing. | 94 // This test doesn't exercise the extraction timing. |
61 EXPECT_CALL(clock_, Now()).WillRepeatedly(Return(base::TimeTicks::Now())); | 95 EXPECT_CALL(clock_, Now()).WillRepeatedly(Return(base::TimeTicks::Now())); |
62 responses_["http://host.com/"] = | 96 responses_["http://host.com/"] = |
63 "<html><head><body>" | 97 "<html><head><body>" |
64 "<form action=\"query\"><input type=text><input type=checkbox></form>" | 98 "<form action=\"query\"><input type=text><input type=checkbox></form>" |
65 "<form action=\"http://cgi.host.com/submit\"></form>" | 99 "<form action=\"http://cgi.host.com/submit\"></form>" |
66 "<form action=\"http://other.com/\"></form>" | 100 "<form action=\"http://other.com/\"></form>" |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 .WillOnce(Return(now + base::TimeDelta::FromMilliseconds(360))) | 349 .WillOnce(Return(now + base::TimeDelta::FromMilliseconds(360))) |
316 // Time check after the next 10 elements. This is over the limit. | 350 // Time check after the next 10 elements. This is over the limit. |
317 .WillOnce(Return(now + base::TimeDelta::FromMilliseconds(600))) | 351 .WillOnce(Return(now + base::TimeDelta::FromMilliseconds(600))) |
318 // A final time check for the histograms. | 352 // A final time check for the histograms. |
319 .WillOnce(Return(now + base::TimeDelta::FromMilliseconds(620))); | 353 .WillOnce(Return(now + base::TimeDelta::FromMilliseconds(620))); |
320 | 354 |
321 features.Clear(); | 355 features.Clear(); |
322 EXPECT_FALSE(ExtractFeatures(&features)); | 356 EXPECT_FALSE(ExtractFeatures(&features)); |
323 } | 357 } |
324 | 358 |
| 359 TEST_F(PhishingDOMFeatureExtractorTest, SubframeRemoval) { |
| 360 // In this test, we'll advance the feature extractor so that it is positioned |
| 361 // inside an iframe, and have it pause due to exceeding the chunk time limit. |
| 362 // Then, prior to continuation, the iframe is removed from the document. |
| 363 // As currently implemented, this should finish extraction from the removed |
| 364 // iframe document. |
| 365 responses_["http://host.com/"] = |
| 366 "<html><head></head><body>" |
| 367 "<iframe src=\"frame.html\" id=\"frame1\"></iframe>" |
| 368 "<form></form></body></html>"; |
| 369 responses_["http://host.com/frame.html"] = |
| 370 "<html><body><p><p><p><input type=password></body></html>"; |
| 371 |
| 372 base::TimeTicks now = base::TimeTicks::Now(); |
| 373 EXPECT_CALL(clock_, Now()) |
| 374 // Time check at the start of extraction. |
| 375 .WillOnce(Return(now)) |
| 376 // Time check at the start of the first chunk of work. |
| 377 .WillOnce(Return(now)) |
| 378 // Time check after the first 10 elements. Enough time has passed |
| 379 // to stop extraction. Schedule the iframe removal to happen as soon as |
| 380 // the feature extractor returns control to the message loop. |
| 381 .WillOnce(DoAll( |
| 382 Invoke(this, &PhishingDOMFeatureExtractorTest::ScheduleRemoveIframe), |
| 383 Return(now + base::TimeDelta::FromMilliseconds(21)))) |
| 384 // Time check at the start of the second chunk of work. |
| 385 .WillOnce(Return(now + base::TimeDelta::FromMilliseconds(25))) |
| 386 // Time check after resuming iteration for the second chunk. |
| 387 .WillOnce(Return(now + base::TimeDelta::FromMilliseconds(27))) |
| 388 // A final time check for the histograms. |
| 389 .WillOnce(Return(now + base::TimeDelta::FromMilliseconds(33))); |
| 390 |
| 391 FeatureMap expected_features; |
| 392 expected_features.AddBooleanFeature(features::kPageHasForms); |
| 393 expected_features.AddBooleanFeature(features::kPageHasPswdInputs); |
| 394 |
| 395 FeatureMap features; |
| 396 LoadURL("http://host.com/"); |
| 397 ASSERT_TRUE(ExtractFeatures(&features)); |
| 398 EXPECT_THAT(features.features(), ContainerEq(expected_features.features())); |
| 399 } |
| 400 |
325 } // namespace safe_browsing | 401 } // namespace safe_browsing |
OLD | NEW |