[Cleanup] Used scoped pointers in KeyedServiceFactory's SetTestingFactory functions.
[chromium-blink-merge.git] / chrome / browser / safe_browsing / incident_reporting / last_download_finder_unittest.cc
blobe1285114b88fd24e9f98c9de5301774adc97f670
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/safe_browsing/incident_reporting/last_download_finder.h"
7 #include <string>
8 #include <vector>
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/files/file_util.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/run_loop.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "chrome/browser/history/chrome_history_client.h"
18 #include "chrome/browser/history/chrome_history_client_factory.h"
19 #include "chrome/browser/history/history_service_factory.h"
20 #include "chrome/browser/history/web_history_service_factory.h"
21 #include "chrome/browser/prefs/browser_prefs.h"
22 #include "chrome/browser/profiles/profile_manager.h"
23 #include "chrome/common/chrome_constants.h"
24 #include "chrome/common/pref_names.h"
25 #include "chrome/common/safe_browsing/csd.pb.h"
26 #include "chrome/test/base/testing_browser_process.h"
27 #include "chrome/test/base/testing_pref_service_syncable.h"
28 #include "chrome/test/base/testing_profile.h"
29 #include "chrome/test/base/testing_profile_manager.h"
30 #include "components/history/content/browser/content_visit_delegate.h"
31 #include "components/history/content/browser/download_constants_utils.h"
32 #include "components/history/content/browser/history_database_helper.h"
33 #include "components/history/core/browser/download_constants.h"
34 #include "components/history/core/browser/download_row.h"
35 #include "components/history/core/browser/history_constants.h"
36 #include "components/history/core/browser/history_database_params.h"
37 #include "components/history/core/browser/history_service.h"
38 #include "content/public/test/test_browser_thread_bundle.h"
39 #include "content/public/test/test_utils.h"
40 #include "testing/gtest/include/gtest/gtest.h"
42 namespace {
44 // A BrowserContextKeyedServiceFactory::TestingFactoryFunction that creates a
45 // HistoryService for a TestingProfile.
46 scoped_ptr<KeyedService> BuildHistoryService(content::BrowserContext* context) {
47 TestingProfile* profile = static_cast<TestingProfile*>(context);
49 // Delete the file before creating the service.
50 base::FilePath history_path(
51 profile->GetPath().Append(history::kHistoryFilename));
52 if (!base::DeleteFile(history_path, false) ||
53 base::PathExists(history_path)) {
54 ADD_FAILURE() << "failed to delete history db file "
55 << history_path.value();
56 return nullptr;
59 scoped_ptr<history::HistoryService> history_service(
60 new history::HistoryService(
61 ChromeHistoryClientFactory::GetForProfile(profile),
62 scoped_ptr<history::VisitDelegate>()));
63 if (history_service->Init(
64 profile->GetPrefs()->GetString(prefs::kAcceptLanguages),
65 history::HistoryDatabaseParamsForPath(profile->GetPath()))) {
66 return history_service.Pass();
69 ADD_FAILURE() << "failed to initialize history service";
70 return nullptr;
73 } // namespace
75 namespace safe_browsing {
77 class LastDownloadFinderTest : public testing::Test {
78 public:
79 void NeverCalled(scoped_ptr<ClientIncidentReport_DownloadDetails> download) {
80 FAIL();
83 // Creates a new profile that participates in safe browsing and adds a
84 // download to its history.
85 void CreateProfileWithDownload() {
86 TestingProfile* profile = CreateProfile(SAFE_BROWSING_OPT_IN);
87 history::HistoryService* history_service =
88 HistoryServiceFactory::GetForProfile(
89 profile, ServiceAccessType::EXPLICIT_ACCESS);
90 history_service->CreateDownload(
91 CreateTestDownloadRow(),
92 base::Bind(&LastDownloadFinderTest::OnDownloadCreated,
93 base::Unretained(this)));
96 // LastDownloadFinder::LastDownloadCallback implementation that
97 // passes the found download to |result| and then runs a closure.
98 void OnLastDownload(
99 scoped_ptr<ClientIncidentReport_DownloadDetails>* result,
100 const base::Closure& quit_closure,
101 scoped_ptr<ClientIncidentReport_DownloadDetails> download) {
102 *result = download.Pass();
103 quit_closure.Run();
106 protected:
107 // A type for specifying whether or not a profile created by CreateProfile
108 // participates in safe browsing.
109 enum SafeBrowsingDisposition {
110 SAFE_BROWSING_OPT_OUT,
111 SAFE_BROWSING_OPT_IN,
114 LastDownloadFinderTest() : profile_number_() {}
116 void SetUp() override {
117 testing::Test::SetUp();
118 profile_manager_.reset(
119 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
120 ASSERT_TRUE(profile_manager_->SetUp());
123 void TearDown() override {
124 // Shut down the history service on all profiles.
125 std::vector<Profile*> profiles(
126 profile_manager_->profile_manager()->GetLoadedProfiles());
127 for (size_t i = 0; i < profiles.size(); ++i) {
128 profiles[0]->AsTestingProfile()->DestroyHistoryService();
130 profile_manager_.reset();
131 TestingBrowserProcess::DeleteInstance();
132 testing::Test::TearDown();
135 TestingProfile* CreateProfile(SafeBrowsingDisposition safe_browsing_opt_in) {
136 std::string profile_name("profile");
137 profile_name.append(base::IntToString(++profile_number_));
139 // Set up keyed service factories.
140 TestingProfile::TestingFactories factories;
141 // Build up a custom history service.
142 factories.push_back(std::make_pair(HistoryServiceFactory::GetInstance(),
143 &BuildHistoryService));
144 // Suppress WebHistoryService since it makes network requests.
145 factories.push_back(std::make_pair(
146 WebHistoryServiceFactory::GetInstance(),
147 static_cast<BrowserContextKeyedServiceFactory::TestingFactoryFunction>(
148 NULL)));
150 // Create prefs for the profile with safe browsing enabled or not.
151 scoped_ptr<TestingPrefServiceSyncable> prefs(
152 new TestingPrefServiceSyncable);
153 chrome::RegisterUserProfilePrefs(prefs->registry());
154 prefs->SetBoolean(prefs::kSafeBrowsingEnabled,
155 safe_browsing_opt_in == SAFE_BROWSING_OPT_IN);
157 TestingProfile* profile = profile_manager_->CreateTestingProfile(
158 profile_name,
159 prefs.Pass(),
160 base::UTF8ToUTF16(profile_name), // user_name
161 0, // avatar_id
162 std::string(), // supervised_user_id
163 factories);
165 return profile;
168 LastDownloadFinder::DownloadDetailsGetter GetDownloadDetailsGetter() {
169 return base::Bind(&LastDownloadFinderTest::GetDownloadDetails,
170 base::Unretained(this));
173 void AddDownload(Profile* profile, const history::DownloadRow& download) {
174 base::RunLoop run_loop;
176 history::HistoryService* history_service =
177 HistoryServiceFactory::GetForProfile(
178 profile, ServiceAccessType::EXPLICIT_ACCESS);
179 history_service->CreateDownload(
180 download,
181 base::Bind(&LastDownloadFinderTest::ContinueOnDownloadCreated,
182 base::Unretained(this),
183 run_loop.QuitClosure()));
184 run_loop.Run();
187 // Wait for the history backend thread to process any outstanding tasks.
188 // This is needed because HistoryService::QueryDownloads uses PostTaskAndReply
189 // to do work on the backend thread and then invoke the caller's callback on
190 // the originating thread. The PostTaskAndReplyRelay holds a reference to the
191 // backend until its RunReplyAndSelfDestruct is called on the originating
192 // thread. This reference MUST be released (on the originating thread,
193 // remember) _before_ calling DestroyHistoryService in TearDown(). See the
194 // giant comment in HistoryService::Cleanup explaining where the backend's
195 // dtor must be run.
196 void FlushHistoryBackend(Profile* profile) {
197 base::RunLoop run_loop;
198 HistoryServiceFactory::GetForProfile(profile,
199 ServiceAccessType::EXPLICIT_ACCESS)
200 ->FlushForTest(run_loop.QuitClosure());
201 run_loop.Run();
202 // Then make sure anything bounced back to the main thread has been handled.
203 base::RunLoop().RunUntilIdle();
206 // Runs the last download finder on all loaded profiles, returning the found
207 // download or an empty pointer if none was found.
208 scoped_ptr<ClientIncidentReport_DownloadDetails> RunLastDownloadFinder() {
209 base::RunLoop run_loop;
211 scoped_ptr<ClientIncidentReport_DownloadDetails> last_download;
213 scoped_ptr<LastDownloadFinder> finder(LastDownloadFinder::Create(
214 GetDownloadDetailsGetter(),
215 base::Bind(&LastDownloadFinderTest::OnLastDownload,
216 base::Unretained(this),
217 &last_download,
218 run_loop.QuitClosure())));
220 if (finder)
221 run_loop.Run();
223 return last_download.Pass();
226 history::DownloadRow CreateTestDownloadRow() {
227 base::Time now(base::Time::Now());
228 return history::DownloadRow(
229 base::FilePath(FILE_PATH_LITERAL("spam.exe")),
230 base::FilePath(FILE_PATH_LITERAL("spam.exe")),
231 std::vector<GURL>(1, GURL("http://www.google.com")), // url_chain
232 GURL(), // referrer
233 "application/octet-stream", // mime_type
234 "application/octet-stream", // original_mime_type
235 now - base::TimeDelta::FromMinutes(10), // start
236 now - base::TimeDelta::FromMinutes(9), // end
237 std::string(), // etag
238 std::string(), // last_modified
239 47LL, // received
240 47LL, // total
241 history::DownloadState::COMPLETE, // download_state
242 history::DownloadDangerType::NOT_DANGEROUS, // danger_type
243 history::ToHistoryDownloadInterruptReason(
244 content::DOWNLOAD_INTERRUPT_REASON_NONE), // interrupt_reason,
245 1, // id
246 false, // download_opened
247 std::string(), // ext_id
248 std::string()); // ext_name
251 void ExpectNoDownloadFound(
252 scoped_ptr<ClientIncidentReport_DownloadDetails> download) {
253 EXPECT_FALSE(download);
256 void ExpectFoundTestDownload(
257 scoped_ptr<ClientIncidentReport_DownloadDetails> download) {
258 ASSERT_TRUE(download);
261 content::TestBrowserThreadBundle browser_thread_bundle_;
262 scoped_ptr<TestingProfileManager> profile_manager_;
264 private:
265 // A HistoryService::DownloadCreateCallback that asserts that the download was
266 // created and runs |closure|.
267 void ContinueOnDownloadCreated(const base::Closure& closure, bool created) {
268 ASSERT_TRUE(created);
269 closure.Run();
272 // A HistoryService::DownloadCreateCallback that asserts that the download was
273 // created.
274 void OnDownloadCreated(bool created) { ASSERT_TRUE(created); }
276 void GetDownloadDetails(
277 content::BrowserContext* context,
278 const DownloadMetadataManager::GetDownloadDetailsCallback& callback) {
279 callback.Run(scoped_ptr<ClientIncidentReport_DownloadDetails>());
282 int profile_number_;
285 // Tests that nothing happens if there are no profiles at all.
286 TEST_F(LastDownloadFinderTest, NoProfiles) {
287 ExpectNoDownloadFound(RunLastDownloadFinder());
290 // Tests that nothing happens other than the callback being invoked if there are
291 // no profiles participating in safe browsing.
292 TEST_F(LastDownloadFinderTest, NoParticipatingProfiles) {
293 // Create a profile with a history service that is opted-out
294 TestingProfile* profile = CreateProfile(SAFE_BROWSING_OPT_OUT);
296 // Add a download.
297 AddDownload(profile, CreateTestDownloadRow());
299 ExpectNoDownloadFound(RunLastDownloadFinder());
302 // Tests that a download is found from a single profile.
303 TEST_F(LastDownloadFinderTest, SimpleEndToEnd) {
304 // Create a profile with a history service that is opted-in.
305 TestingProfile* profile = CreateProfile(SAFE_BROWSING_OPT_IN);
307 // Add a download.
308 AddDownload(profile, CreateTestDownloadRow());
310 ExpectFoundTestDownload(RunLastDownloadFinder());
313 // Tests that there is no crash if the finder is deleted before results arrive.
314 TEST_F(LastDownloadFinderTest, DeleteBeforeResults) {
315 // Create a profile with a history service that is opted-in.
316 TestingProfile* profile = CreateProfile(SAFE_BROWSING_OPT_IN);
318 // Add a download.
319 AddDownload(profile, CreateTestDownloadRow());
321 // Start a finder and kill it before the search completes.
322 LastDownloadFinder::Create(GetDownloadDetailsGetter(),
323 base::Bind(&LastDownloadFinderTest::NeverCalled,
324 base::Unretained(this))).reset();
326 // Flush tasks on the history backend thread.
327 FlushHistoryBackend(profile);
330 // Tests that a download in profile added after the search is begun is found.
331 TEST_F(LastDownloadFinderTest, AddProfileAfterStarting) {
332 // Create a profile with a history service that is opted-in.
333 CreateProfile(SAFE_BROWSING_OPT_IN);
335 scoped_ptr<ClientIncidentReport_DownloadDetails> last_download;
336 base::RunLoop run_loop;
338 // Post a task that will create a second profile once the main loop is run.
339 base::MessageLoop::current()->PostTask(
340 FROM_HERE,
341 base::Bind(&LastDownloadFinderTest::CreateProfileWithDownload,
342 base::Unretained(this)));
344 // Create a finder that we expect will find a download in the second profile.
345 scoped_ptr<LastDownloadFinder> finder(LastDownloadFinder::Create(
346 GetDownloadDetailsGetter(),
347 base::Bind(&LastDownloadFinderTest::OnLastDownload,
348 base::Unretained(this),
349 &last_download,
350 run_loop.QuitClosure())));
352 run_loop.Run();
354 ExpectFoundTestDownload(last_download.Pass());
357 } // namespace safe_browsing