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

Unified Diff: chrome/browser/safe_browsing/incident_reporting/off_domain_inclusion_detector_unittest.cc

Issue 859903002: Compare non-whitelisted off-domain inclusions against the browsing history. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@#c3_ODID_async
Patch Set: GMOCK, nit, and compile fix Created 5 years, 11 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/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..5f6afe4d6514e2cb973f91a015547918473033d2 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,37 @@
// 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/content/browser/history_database_helper.h"
+#include "components/history/core/browser/history_constants.h"
+#include "components/history/core/browser/history_database_params.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"
@@ -21,10 +42,44 @@
#include "url/gurl.h"
using testing::_;
+using testing::Eq;
using testing::NiceMock;
using testing::Return;
using testing::Values;
+namespace {
+
+const int kFakeRenderProcessId = 123;
+
+// 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(
+ history::HistoryDatabaseParamsForPath(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;
@@ -61,9 +116,11 @@ static_assert(
"Expected resource types list aren't comprehensive");
// A set of test cases to run each parametrized test case below through.
-enum class OffDomainInclusionTestCases {
- OFF_DOMAIN_INCLUSION_WHITELISTED,
- OFF_DOMAIN_INCLUSION_UNKNOWN,
+enum class TestCase {
+ WHITELISTED,
+ IN_HISTORY,
+ IN_HISTORY_AND_WHITELISTED,
+ UNKNOWN,
};
class MockSafeBrowsingDatabaseManager : public SafeBrowsingDatabaseManager {
@@ -81,29 +138,74 @@ class MockSafeBrowsingDatabaseManager : public SafeBrowsingDatabaseManager {
DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingDatabaseManager);
};
-class OffDomainInclusionDetectorTest
- : public testing::TestWithParam<OffDomainInclusionTestCases> {
+// A mock OffDomainInclusionDetector which mocks out
+// |ProfileFromRenderProcessId()| so that tests can inject their TestingProfile
+// into the OffDomainInclusionDetector.
+class MockOffDomainInclusionDetector
+ : public NiceMock<OffDomainInclusionDetector> {
+ public:
+ MockOffDomainInclusionDetector(
+ const scoped_refptr<SafeBrowsingDatabaseManager>& database_manager,
+ const ReportAnalysisEventCallback& report_analysis_event_callback)
+ : NiceMock<OffDomainInclusionDetector>(database_manager,
+ report_analysis_event_callback) {}
+
+ MOCK_METHOD1(ProfileFromRenderProcessId, Profile*(int render_process_id));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockOffDomainInclusionDetector);
+};
+
+// 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<TestCase> {
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 +214,21 @@ 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 +237,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
+ 0, // render_frame_id
is_main_frame, // is_main_frame
parent_is_main_frame, // parent_is_main_frame
true, // allow_download
@@ -137,35 +247,132 @@ 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() {
- return GetParam() ==
- OffDomainInclusionTestCases::OFF_DOMAIN_INCLUSION_WHITELISTED
- ? AnalysisEvent::OFF_DOMAIN_INCLUSION_WHITELISTED
- : AnalysisEvent::OFF_DOMAIN_INCLUSION_SUSPICIOUS;
+ switch (GetParam()) {
+ case TestCase::WHITELISTED:
+ return AnalysisEvent::OFF_DOMAIN_INCLUSION_WHITELISTED;
+ case TestCase::IN_HISTORY:
+ return AnalysisEvent::OFF_DOMAIN_INCLUSION_IN_HISTORY;
+ case TestCase::IN_HISTORY_AND_WHITELISTED:
+ return AnalysisEvent::OFF_DOMAIN_INCLUSION_WHITELISTED;
+ case TestCase::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() == TestCase::WHITELISTED ||
+ GetParam() == TestCase::IN_HISTORY_AND_WHITELISTED;
+ }
+
+ // Returns true if simulated URLs should be added to history.
+ bool ShouldAddSimulatedURLsToHistory() const {
+ return GetParam() == TestCase::IN_HISTORY ||
+ GetParam() == TestCase::IN_HISTORY_AND_WHITELISTED;
+ }
+
void OnOffDomainInclusionEvent(AnalysisEvent event) {
// Make sure no other AnalysisEvent was previously reported.
EXPECT_EQ(AnalysisEvent::NO_EVENT, observed_analysis_event_);
observed_analysis_event_ = event;
}
+ // Initializes |profile_manager_| and |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);
+ }
+
+ // Initializes |off_domain_inclusion_detector_|, assumes |testing_profile_| is
+ // already initialized.
+ void InitOffDomainInclusionDetector() {
+ ASSERT_TRUE(testing_profile_);
+ 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 MockOffDomainInclusionDetector(
grt (UTC plus 2) 2015/01/28 21:10:51 new NiceMock<MockOffDomainInclusionDetector> here
+ mock_safe_browsing_database_manager,
+ base::Bind(&OffDomainInclusionDetectorTest::OnOffDomainInclusionEvent,
+ base::Unretained(this))));
+ // ProfileFromRenderProcessId doesn't *have* to be called, but if it is, it
+ // should always request the profile for |kFakeRenderProcessId| and this
+ // test will always return it |testing_profile_|.
+ ON_CALL(*off_domain_inclusion_detector_,
+ ProfileFromRenderProcessId(Eq(kFakeRenderProcessId)))
+ .WillByDefault(Return(testing_profile_));
+ }
+
+ 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_;
+ scoped_ptr<MockOffDomainInclusionDetector> off_domain_inclusion_detector_;
+
+ DISALLOW_COPY_AND_ASSIGN(OffDomainInclusionDetectorTest);
};
TEST_P(OffDomainInclusionDetectorTest, NoEventForIgnoredResourceTypes) {
@@ -334,14 +541,16 @@ 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());
}
}
-INSTANTIATE_TEST_CASE_P(
- OffDomainInclusionDetectorTestInstance,
- OffDomainInclusionDetectorTest,
- Values(OffDomainInclusionTestCases::OFF_DOMAIN_INCLUSION_WHITELISTED,
- OffDomainInclusionTestCases::OFF_DOMAIN_INCLUSION_UNKNOWN));
+INSTANTIATE_TEST_CASE_P(OffDomainInclusionDetectorTestInstance,
+ OffDomainInclusionDetectorTest,
+ Values(TestCase::WHITELISTED,
+ TestCase::IN_HISTORY,
+ TestCase::IN_HISTORY_AND_WHITELISTED,
+ TestCase::UNKNOWN));
} // namespace safe_browsing

Powered by Google App Engine
This is Rietveld 408576698