Index: chrome/browser/safe_browsing/incident_reporting/off_domain_inclusion_detector_unittest.cc |
diff --git a/chrome/browser/safe_browsing/incident_reporting/off_domain_inclusion_detector_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/off_domain_inclusion_detector_unittest.cc |
index 4860a455d611c97fbe729e022981f34870d918e9..315e59d0bf3c87fd67df4fc8e6a606c860356b05 100644 |
--- a/chrome/browser/safe_browsing/incident_reporting/off_domain_inclusion_detector_unittest.cc |
+++ b/chrome/browser/safe_browsing/incident_reporting/off_domain_inclusion_detector_unittest.cc |
@@ -3,16 +3,35 @@ |
// found in the LICENSE file. |
#include "base/bind.h" |
+#include "base/files/file_util.h" |
+#include "base/logging.h" |
#include "base/memory/ref_counted.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/run_loop.h" |
+#include "base/strings/string_number_conversions.h" |
+#include "base/strings/utf_string_conversions.h" |
+#include "base/time/time.h" |
+#include "chrome/browser/history/chrome_history_client.h" |
+#include "chrome/browser/history/chrome_history_client_factory.h" |
+#include "chrome/browser/history/history_service.h" |
+#include "chrome/browser/history/history_service_factory.h" |
+#include "chrome/browser/history/web_history_service_factory.h" |
+#include "chrome/browser/prefs/browser_prefs.h" |
+#include "chrome/browser/profiles/profile.h" |
+#include "chrome/browser/profiles/profile_manager.h" |
#include "chrome/browser/safe_browsing/database_manager.h" |
#include "chrome/browser/safe_browsing/incident_reporting/off_domain_inclusion_detector.h" |
#include "chrome/browser/safe_browsing/safe_browsing_service.h" |
+#include "chrome/test/base/testing_browser_process.h" |
+#include "chrome/test/base/testing_pref_service_syncable.h" |
+#include "chrome/test/base/testing_profile.h" |
+#include "chrome/test/base/testing_profile_manager.h" |
+#include "components/history/core/browser/history_constants.h" |
+#include "components/history/core/browser/history_types.h" |
+#include "components/keyed_service/core/service_access_type.h" |
#include "content/public/browser/resource_request_info.h" |
#include "content/public/common/resource_type.h" |
#include "content/public/test/test_browser_thread_bundle.h" |
-#include "ipc/ipc_message.h" |
#include "net/base/request_priority.h" |
#include "net/url_request/url_request.h" |
#include "net/url_request/url_request_test_util.h" |
@@ -25,6 +44,38 @@ using testing::NiceMock; |
using testing::Return; |
using testing::Values; |
+namespace { |
+ |
+const int kFakeRenderProcessId = 123; |
+const int kFakeRenderFrameId = 456; |
+ |
+// A BrowserContextKeyedServiceFactory::TestingFactoryFunction that creates a |
+// HistoryService for a TestingProfile. |
+KeyedService* BuildHistoryService(content::BrowserContext* context) { |
+ TestingProfile* profile = static_cast<TestingProfile*>(context); |
+ |
+ // Delete the file before creating the service. |
+ base::FilePath history_path( |
+ profile->GetPath().Append(history::kHistoryFilename)); |
+ if (!base::DeleteFile(history_path, false) || |
+ base::PathExists(history_path)) { |
+ ADD_FAILURE() << "failed to delete history db file " |
+ << history_path.value(); |
+ return NULL; |
+ } |
+ |
+ HistoryService* history_service = new HistoryService( |
+ ChromeHistoryClientFactory::GetForProfile(profile), profile); |
+ if (history_service->Init(profile->GetPath())) |
+ return history_service; |
+ |
+ ADD_FAILURE() << "failed to initialize history service"; |
+ delete history_service; |
+ return NULL; |
+} |
+ |
+} // namespace |
+ |
namespace safe_browsing { |
using AnalysisEvent = OffDomainInclusionDetector::AnalysisEvent; |
@@ -63,6 +114,8 @@ static_assert( |
// A set of test cases to run each parametrized test case below through. |
enum class OffDomainInclusionTestCases { |
OFF_DOMAIN_INCLUSION_WHITELISTED, |
+ OFF_DOMAIN_INCLUSION_IN_HISTORY, |
+ OFF_DOMAIN_INCLUSION_IN_HISTORY_AND_WHITELISTED, |
OFF_DOMAIN_INCLUSION_UNKNOWN, |
}; |
@@ -81,29 +134,57 @@ class MockSafeBrowsingDatabaseManager : public SafeBrowsingDatabaseManager { |
DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingDatabaseManager); |
}; |
+// Adds |url| to |history_service| upon being constructed and removes it upon |
+// being destructed. |
+class ScopedHistoryEntry { |
+ public: |
+ ScopedHistoryEntry(HistoryService* history_service, const GURL& url) |
+ : history_service_(history_service), url_(url) { |
+ base::RunLoop run_loop; |
+ |
+ history_service_->AddPage(url_, base::Time::Now(), history::SOURCE_BROWSED); |
+ |
+ // Flush tasks posted on the history thread. |
+ history_service_->FlushForTest(run_loop.QuitClosure()); |
+ run_loop.Run(); |
+ // Make sure anything bounced back to the main thread has been handled. |
+ base::RunLoop().RunUntilIdle(); |
+ } |
+ |
+ ~ScopedHistoryEntry() { |
+ base::RunLoop run_loop; |
+ |
+ history_service_->DeleteURL(url_); |
+ |
+ history_service_->FlushForTest(run_loop.QuitClosure()); |
+ run_loop.Run(); |
+ base::RunLoop().RunUntilIdle(); |
+ } |
+ |
+ private: |
+ HistoryService* history_service_; |
+ const GURL url_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ScopedHistoryEntry); |
+}; |
+ |
class OffDomainInclusionDetectorTest |
: public testing::TestWithParam<OffDomainInclusionTestCases> { |
protected: |
OffDomainInclusionDetectorTest() |
- : observed_analysis_event_(AnalysisEvent::NO_EVENT) {} |
+ : testing_profile_(nullptr), |
+ observed_analysis_event_(AnalysisEvent::NO_EVENT) {} |
void SetUp() override { |
- // Only used for initializing MockSafeBrowsingDatabaseManager. |
- scoped_refptr<SafeBrowsingService> sb_service = |
- SafeBrowsingService::CreateSafeBrowsingService(); |
- |
- scoped_refptr<MockSafeBrowsingDatabaseManager> |
- mock_safe_browsing_database_manager = |
- new NiceMock<MockSafeBrowsingDatabaseManager>(sb_service); |
- ON_CALL(*mock_safe_browsing_database_manager, MatchInclusionWhitelistUrl(_)) |
- .WillByDefault(Return( |
- GetParam() == |
- OffDomainInclusionTestCases::OFF_DOMAIN_INCLUSION_WHITELISTED)); |
+ InitTestProfile(); |
+ InitOffDomainInclusionDetector(); |
+ } |
- off_domain_inclusion_detector_.reset(new OffDomainInclusionDetector( |
- mock_safe_browsing_database_manager, |
- base::Bind(&OffDomainInclusionDetectorTest::OnOffDomainInclusionEvent, |
- base::Unretained(this)))); |
+ void TearDown() override { |
+ // Shut down the history service. |
+ testing_profile_->AsTestingProfile()->DestroyHistoryService(); |
+ profile_manager_.reset(); |
+ TestingBrowserProcess::DeleteInstance(); |
} |
AnalysisEvent GetLastEventAndReset() { |
@@ -112,13 +193,23 @@ class OffDomainInclusionDetectorTest |
return last_event; |
} |
- void SimulateTestURLRequest(const std::string& url, |
+ void SimulateTestURLRequest(const std::string& url_str, |
const std::string& referrer, |
content::ResourceType resource_type, |
bool is_main_frame, |
bool parent_is_main_frame) const { |
+ const GURL url(url_str); |
+ |
+ HistoryService* history_service = HistoryServiceFactory::GetForProfile( |
+ testing_profile_, ServiceAccessType::EXPLICIT_ACCESS); |
+ scoped_ptr<ScopedHistoryEntry> scoped_history_entry; |
+ if (ShouldAddSimulatedURLsToHistory()) { |
+ scoped_history_entry.reset( |
+ new ScopedHistoryEntry(history_service, url)); |
+ } |
+ |
scoped_ptr<net::URLRequest> url_request( |
- context_.CreateRequest(GURL(url), net::DEFAULT_PRIORITY, NULL, NULL)); |
+ context_.CreateRequest(url, net::DEFAULT_PRIORITY, NULL, NULL)); |
if (!referrer.empty()) |
url_request->SetReferrer(referrer); |
@@ -127,9 +218,9 @@ class OffDomainInclusionDetectorTest |
url_request.get(), |
resource_type, |
NULL, // resource_context |
- 0, // render_process_id |
+ kFakeRenderProcessId, // render_process_id |
0, // render_view_id |
- MSG_ROUTING_NONE, // render_frame_id |
+ kFakeRenderFrameId, // render_frame_id |
is_main_frame, // is_main_frame |
parent_is_main_frame, // parent_is_main_frame |
true, // allow_download |
@@ -137,35 +228,137 @@ class OffDomainInclusionDetectorTest |
off_domain_inclusion_detector_->OnResourceRequest(url_request.get()); |
- // OffDomainInclusionDetector::OnResourceRequest() sometimes completes |
+ // OffDomainInclusionDetector::OnResourceRequest() may complete |
// asynchronously, run all message loops (i.e. this message loop in unit |
// tests) until idle. |
base::RunLoop().RunUntilIdle(); |
+ |
+ // Make sure any task posted by the OffDomainInclusionDetector to the |
+ // history thread has occurred. |
+ base::RunLoop run_loop; |
+ history_service->FlushForTest(run_loop.QuitClosure()); |
+ run_loop.Run(); |
+ |
+ // Finally, finish anything the history thread may have bounced back to the |
+ // main thread. |
+ base::RunLoop().RunUntilIdle(); |
} |
// Returns the expected AnalysisEvent produced when facing an off-domain |
// inclusion in the current test configuration. |
AnalysisEvent GetExpectedOffDomainInclusionEventType() { |
+ switch (GetParam()) { |
+ case OffDomainInclusionTestCases::OFF_DOMAIN_INCLUSION_WHITELISTED: |
+ return AnalysisEvent::OFF_DOMAIN_INCLUSION_WHITELISTED; |
+ case OffDomainInclusionTestCases::OFF_DOMAIN_INCLUSION_IN_HISTORY: |
+ return AnalysisEvent::OFF_DOMAIN_INCLUSION_IN_HISTORY; |
+ case OffDomainInclusionTestCases:: |
+ OFF_DOMAIN_INCLUSION_IN_HISTORY_AND_WHITELISTED: |
+ return AnalysisEvent::OFF_DOMAIN_INCLUSION_WHITELISTED; |
+ case OffDomainInclusionTestCases::OFF_DOMAIN_INCLUSION_UNKNOWN: |
+ return AnalysisEvent::OFF_DOMAIN_INCLUSION_SUSPICIOUS; |
+ } |
+ NOTREACHED(); |
+ return AnalysisEvent::NO_EVENT; |
+ } |
+ |
+ private: |
+ // Returns true if the inclusion whitelist should be mocked to return a match |
+ // on all requests. |
+ bool ShouldWhitelistEverything() const { |
return GetParam() == |
- OffDomainInclusionTestCases::OFF_DOMAIN_INCLUSION_WHITELISTED |
- ? AnalysisEvent::OFF_DOMAIN_INCLUSION_WHITELISTED |
- : AnalysisEvent::OFF_DOMAIN_INCLUSION_SUSPICIOUS; |
+ OffDomainInclusionTestCases::OFF_DOMAIN_INCLUSION_WHITELISTED || |
Alexei Svitkine (slow)
2015/01/20 22:24:57
Nit: Given this is in off_domain_inclusion_detecto
gab
2015/01/23 21:35:33
Done, still like using enum class, but cleaned up
|
+ GetParam() == OffDomainInclusionTestCases:: |
+ OFF_DOMAIN_INCLUSION_IN_HISTORY_AND_WHITELISTED; |
} |
+ // Returns true if simulated URLs should be added to history. |
+ bool ShouldAddSimulatedURLsToHistory() const { |
+ return GetParam() == |
+ OffDomainInclusionTestCases::OFF_DOMAIN_INCLUSION_IN_HISTORY || |
+ GetParam() == OffDomainInclusionTestCases:: |
+ OFF_DOMAIN_INCLUSION_IN_HISTORY_AND_WHITELISTED; |
+ } |
- private: |
void OnOffDomainInclusionEvent(AnalysisEvent event) { |
// Make sure no other AnalysisEvent was previously reported. |
EXPECT_EQ(AnalysisEvent::NO_EVENT, observed_analysis_event_); |
observed_analysis_event_ = event; |
} |
+ Profile* GetTestProfileForTestRenderFrameId(int render_process_id, |
+ int render_frame_id) { |
+ EXPECT_EQ(kFakeRenderProcessId, render_process_id); |
+ EXPECT_EQ(kFakeRenderFrameId, render_frame_id); |
+ return testing_profile_; |
+ } |
+ |
+ void InitTestProfile() { |
+ ASSERT_FALSE(profile_manager_); |
+ ASSERT_FALSE(testing_profile_); |
+ |
+ profile_manager_.reset( |
+ new TestingProfileManager(TestingBrowserProcess::GetGlobal())); |
+ ASSERT_TRUE(profile_manager_->SetUp()); |
+ |
+ // Set up a mock keyed service factory for the HistoryService. |
+ TestingProfile::TestingFactories factories; |
+ factories.push_back(std::make_pair(HistoryServiceFactory::GetInstance(), |
+ &BuildHistoryService)); |
+ // Suppress WebHistoryService since it makes network requests. |
+ factories.push_back(std::make_pair( |
+ WebHistoryServiceFactory::GetInstance(), |
+ static_cast<BrowserContextKeyedServiceFactory::TestingFactoryFunction>( |
+ NULL))); |
+ |
+ // Create default prefs for the test profile. |
+ scoped_ptr<TestingPrefServiceSyncable> prefs( |
+ new TestingPrefServiceSyncable); |
+ chrome::RegisterUserProfilePrefs(prefs->registry()); |
+ |
+ // |testing_profile_| is owned by |profile_manager_|. |
+ testing_profile_ = profile_manager_->CreateTestingProfile( |
+ "profile", // profile_name |
+ prefs.Pass(), |
+ base::UTF8ToUTF16("user"), // user_name |
+ 0, // avatar_id |
+ std::string(), // supervised_user_id |
+ factories); |
+ } |
+ |
+ void InitOffDomainInclusionDetector() { |
+ ASSERT_FALSE(off_domain_inclusion_detector_); |
+ |
+ // Only used for initializing MockSafeBrowsingDatabaseManager. |
+ scoped_refptr<SafeBrowsingService> sb_service = |
+ SafeBrowsingService::CreateSafeBrowsingService(); |
+ |
+ scoped_refptr<MockSafeBrowsingDatabaseManager> |
+ mock_safe_browsing_database_manager = |
+ new NiceMock<MockSafeBrowsingDatabaseManager>(sb_service); |
+ ON_CALL(*mock_safe_browsing_database_manager, MatchInclusionWhitelistUrl(_)) |
+ .WillByDefault(Return(ShouldWhitelistEverything())); |
+ |
+ off_domain_inclusion_detector_.reset(new OffDomainInclusionDetector( |
+ mock_safe_browsing_database_manager, |
+ base::Bind(&OffDomainInclusionDetectorTest::OnOffDomainInclusionEvent, |
+ base::Unretained(this)), |
+ base::Bind( |
+ &OffDomainInclusionDetectorTest::GetTestProfileForTestRenderFrameId, |
+ base::Unretained(this)))); |
+ } |
+ |
+ Profile* testing_profile_; |
+ scoped_ptr<TestingProfileManager> profile_manager_; |
+ |
content::TestBrowserThreadBundle thread_bundle_; |
net::TestURLRequestContext context_; |
AnalysisEvent observed_analysis_event_; |
scoped_ptr<OffDomainInclusionDetector> off_domain_inclusion_detector_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(OffDomainInclusionDetectorTest); |
}; |
TEST_P(OffDomainInclusionDetectorTest, NoEventForIgnoredResourceTypes) { |
@@ -334,7 +527,8 @@ TEST_P(OffDomainInclusionDetectorTest, |
true, // is_main_frame |
false); // parent_is_main_frame |
- EXPECT_EQ(AnalysisEvent::EMPTY_MAIN_FRAME_URL, GetLastEventAndReset()); |
+ EXPECT_EQ(AnalysisEvent::ABORT_EMPTY_MAIN_FRAME_URL, |
+ GetLastEventAndReset()); |
} |
} |
@@ -342,6 +536,9 @@ INSTANTIATE_TEST_CASE_P( |
OffDomainInclusionDetectorTestInstance, |
OffDomainInclusionDetectorTest, |
Values(OffDomainInclusionTestCases::OFF_DOMAIN_INCLUSION_WHITELISTED, |
+ OffDomainInclusionTestCases::OFF_DOMAIN_INCLUSION_IN_HISTORY, |
+ OffDomainInclusionTestCases:: |
+ OFF_DOMAIN_INCLUSION_IN_HISTORY_AND_WHITELISTED, |
OffDomainInclusionTestCases::OFF_DOMAIN_INCLUSION_UNKNOWN)); |
} // namespace safe_browsing |