Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / safe_browsing / incident_reporting / last_download_finder_unittest.cc
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.
4
5 #include "chrome/browser/safe_browsing/incident_reporting/last_download_finder.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/file_util.h"
13 #include "base/run_loop.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "chrome/browser/history/chrome_history_client.h"
17 #include "chrome/browser/history/chrome_history_client_factory.h"
18 #include "chrome/browser/history/download_row.h"
19 #include "chrome/browser/history/history_service.h"
20 #include "chrome/browser/history/history_service_factory.h"
21 #include "chrome/browser/history/web_history_service_factory.h"
22 #include "chrome/browser/prefs/browser_prefs.h"
23 #include "chrome/browser/profiles/profile_manager.h"
24 #include "chrome/common/chrome_constants.h"
25 #include "chrome/common/pref_names.h"
26 #include "chrome/common/safe_browsing/csd.pb.h"
27 #include "chrome/test/base/testing_browser_process.h"
28 #include "chrome/test/base/testing_pref_service_syncable.h"
29 #include "chrome/test/base/testing_profile.h"
30 #include "chrome/test/base/testing_profile_manager.h"
31 #include "content/public/test/test_browser_thread_bundle.h"
32 #include "content/public/test/test_utils.h"
33 #include "testing/gtest/include/gtest/gtest.h"
34
35 namespace {
36
37 // A BrowserContextKeyedServiceFactory::TestingFactoryFunction that creates a
38 // HistoryService for a TestingProfile.
39 KeyedService* BuildHistoryService(content::BrowserContext* context) {
40   TestingProfile* profile = static_cast<TestingProfile*>(context);
41
42   // Delete the file before creating the service.
43   base::FilePath history_path(
44       profile->GetPath().Append(chrome::kHistoryFilename));
45   if (!base::DeleteFile(history_path, false) ||
46       base::PathExists(history_path)) {
47     ADD_FAILURE() << "failed to delete history db file "
48                   << history_path.value();
49     return NULL;
50   }
51
52   HistoryService* history_service = new HistoryService(
53       ChromeHistoryClientFactory::GetForProfile(profile), profile);
54   if (history_service->Init(profile->GetPath()))
55     return history_service;
56
57   ADD_FAILURE() << "failed to initialize history service";
58   delete history_service;
59   return NULL;
60 }
61
62 }  // namespace
63
64 class LastDownloadFinderTest : public testing::Test {
65  public:
66   void NeverCalled(scoped_ptr<
67       safe_browsing::ClientIncidentReport_DownloadDetails> download) {
68     FAIL();
69   }
70
71   // Creates a new profile that participates in safe browsing and adds a
72   // download to its history.
73   void CreateProfileWithDownload() {
74     TestingProfile* profile = CreateProfile(SAFE_BROWSING_OPT_IN);
75     HistoryService* history_service =
76         HistoryServiceFactory::GetForProfile(profile, Profile::EXPLICIT_ACCESS);
77     history_service->CreateDownload(
78         CreateTestDownloadRow(),
79         base::Bind(&LastDownloadFinderTest::OnDownloadCreated,
80                    base::Unretained(this)));
81   }
82
83   // safe_browsing::LastDownloadFinder::LastDownloadCallback implementation that
84   // passes the found download to |result| and then runs a closure.
85   void OnLastDownload(
86       scoped_ptr<safe_browsing::ClientIncidentReport_DownloadDetails>* result,
87       const base::Closure& quit_closure,
88       scoped_ptr<safe_browsing::ClientIncidentReport_DownloadDetails>
89           download) {
90     *result = download.Pass();
91     quit_closure.Run();
92   }
93
94  protected:
95   // A type for specifying whether or not a profile created by CreateProfile
96   // participates in safe browsing.
97   enum SafeBrowsingDisposition {
98     SAFE_BROWSING_OPT_OUT,
99     SAFE_BROWSING_OPT_IN,
100   };
101
102   LastDownloadFinderTest() : profile_number_() {}
103
104   virtual void SetUp() OVERRIDE {
105     testing::Test::SetUp();
106     profile_manager_.reset(
107         new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
108     ASSERT_TRUE(profile_manager_->SetUp());
109   }
110
111   virtual void TearDown() OVERRIDE {
112     // Shut down the history service on all profiles.
113     std::vector<Profile*> profiles(
114         profile_manager_->profile_manager()->GetLoadedProfiles());
115     for (size_t i = 0; i < profiles.size(); ++i) {
116       profiles[0]->AsTestingProfile()->DestroyHistoryService();
117     }
118     profile_manager_.reset();
119     TestingBrowserProcess::DeleteInstance();
120     testing::Test::TearDown();
121   }
122
123   TestingProfile* CreateProfile(SafeBrowsingDisposition safe_browsing_opt_in) {
124     std::string profile_name("profile");
125     profile_name.append(base::IntToString(++profile_number_));
126
127     // Set up keyed service factories.
128     TestingProfile::TestingFactories factories;
129     // Build up a custom history service.
130     factories.push_back(std::make_pair(HistoryServiceFactory::GetInstance(),
131                                        &BuildHistoryService));
132     // Suppress WebHistoryService since it makes network requests.
133     factories.push_back(std::make_pair(
134         WebHistoryServiceFactory::GetInstance(),
135         static_cast<BrowserContextKeyedServiceFactory::TestingFactoryFunction>(
136             NULL)));
137
138     // Create prefs for the profile with safe browsing enabled or not.
139     scoped_ptr<TestingPrefServiceSyncable> prefs(
140         new TestingPrefServiceSyncable);
141     chrome::RegisterUserProfilePrefs(prefs->registry());
142     prefs->SetBoolean(prefs::kSafeBrowsingEnabled,
143                       safe_browsing_opt_in == SAFE_BROWSING_OPT_IN);
144
145     TestingProfile* profile = profile_manager_->CreateTestingProfile(
146         profile_name,
147         prefs.PassAs<PrefServiceSyncable>(),
148         base::UTF8ToUTF16(profile_name),  // user_name
149         0,                                // avatar_id
150         std::string(),                    // supervised_user_id
151         factories);
152
153     return profile;
154   }
155
156   void AddDownload(Profile* profile, const history::DownloadRow& download) {
157     base::RunLoop run_loop;
158
159     HistoryService* history_service =
160         HistoryServiceFactory::GetForProfile(profile, Profile::EXPLICIT_ACCESS);
161     history_service->CreateDownload(
162         download,
163         base::Bind(&LastDownloadFinderTest::ContinueOnDownloadCreated,
164                    base::Unretained(this),
165                    run_loop.QuitClosure()));
166     run_loop.Run();
167   }
168
169   // Wait for the history backend thread to process any outstanding tasks.
170   // This is needed because HistoryService::QueryDownloads uses PostTaskAndReply
171   // to do work on the backend thread and then invoke the caller's callback on
172   // the originating thread. The PostTaskAndReplyRelay holds a reference to the
173   // backend until its RunReplyAndSelfDestruct is called on the originating
174   // thread. This reference MUST be released (on the originating thread,
175   // remember) _before_ calling DestroyHistoryService in TearDown(). See the
176   // giant comment in HistoryService::Cleanup explaining where the backend's
177   // dtor must be run.
178   void FlushHistoryBackend(Profile* profile) {
179     base::RunLoop run_loop;
180     HistoryServiceFactory::GetForProfile(profile, Profile::EXPLICIT_ACCESS)
181         ->FlushForTest(run_loop.QuitClosure());
182     run_loop.Run();
183     // Then make sure anything bounced back to the main thread has been handled.
184     base::RunLoop().RunUntilIdle();
185   }
186
187   // Runs the last download finder on all loaded profiles, returning the found
188   // download or an empty pointer if none was found.
189   scoped_ptr<safe_browsing::ClientIncidentReport_DownloadDetails>
190   RunLastDownloadFinder() {
191     base::RunLoop run_loop;
192
193     scoped_ptr<safe_browsing::ClientIncidentReport_DownloadDetails>
194         last_download;
195
196     scoped_ptr<safe_browsing::LastDownloadFinder> finder(
197         safe_browsing::LastDownloadFinder::Create(
198             base::Bind(&LastDownloadFinderTest::OnLastDownload,
199                        base::Unretained(this),
200                        &last_download,
201                        run_loop.QuitClosure())));
202
203     if (finder)
204       run_loop.Run();
205
206     return last_download.Pass();
207   }
208
209   history::DownloadRow CreateTestDownloadRow() {
210     base::Time now(base::Time::Now());
211     return history::DownloadRow(
212         base::FilePath(FILE_PATH_LITERAL("spam.exe")),
213         base::FilePath(FILE_PATH_LITERAL("spam.exe")),
214         std::vector<GURL>(1, GURL("http://www.google.com")),  // url_chain
215         GURL(),                                               // referrer
216         "application/octet-stream",                           // mime_type
217         "application/octet-stream",                   // original_mime_type
218         now - base::TimeDelta::FromMinutes(10),       // start
219         now - base::TimeDelta::FromMinutes(9),        // end
220         std::string(),                                // etag
221         std::string(),                                // last_modified
222         47LL,                                         // received
223         47LL,                                         // total
224         content::DownloadItem::COMPLETE,              // download_state
225         content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,  // danger_type
226         content::DOWNLOAD_INTERRUPT_REASON_NONE,      // interrupt_reason,
227         1,                                            // id
228         false,                                        // download_opened
229         std::string(),                                // ext_id
230         std::string());                               // ext_name
231   }
232
233   void ExpectNoDownloadFound(scoped_ptr<
234       safe_browsing::ClientIncidentReport_DownloadDetails> download) {
235     EXPECT_FALSE(download);
236   }
237
238   void ExpectFoundTestDownload(scoped_ptr<
239       safe_browsing::ClientIncidentReport_DownloadDetails> download) {
240     ASSERT_TRUE(download);
241   }
242
243   content::TestBrowserThreadBundle browser_thread_bundle_;
244   scoped_ptr<TestingProfileManager> profile_manager_;
245
246  private:
247   // A HistoryService::DownloadCreateCallback that asserts that the download was
248   // created and runs |closure|.
249   void ContinueOnDownloadCreated(const base::Closure& closure, bool created) {
250     ASSERT_TRUE(created);
251     closure.Run();
252   }
253
254   // A HistoryService::DownloadCreateCallback that asserts that the download was
255   // created.
256   void OnDownloadCreated(bool created) { ASSERT_TRUE(created); }
257
258   int profile_number_;
259 };
260
261 // Tests that nothing happens if there are no profiles at all.
262 TEST_F(LastDownloadFinderTest, NoProfiles) {
263   ExpectNoDownloadFound(RunLastDownloadFinder());
264 }
265
266 // Tests that nothing happens other than the callback being invoked if there are
267 // no profiles participating in safe browsing.
268 TEST_F(LastDownloadFinderTest, NoParticipatingProfiles) {
269   // Create a profile with a history service that is opted-out
270   TestingProfile* profile = CreateProfile(SAFE_BROWSING_OPT_OUT);
271
272   // Add a download.
273   AddDownload(profile, CreateTestDownloadRow());
274
275   ExpectNoDownloadFound(RunLastDownloadFinder());
276 }
277
278 // Tests that a download is found from a single profile.
279 TEST_F(LastDownloadFinderTest, SimpleEndToEnd) {
280   // Create a profile with a history service that is opted-in.
281   TestingProfile* profile = CreateProfile(SAFE_BROWSING_OPT_IN);
282
283   // Add a download.
284   AddDownload(profile, CreateTestDownloadRow());
285
286   ExpectFoundTestDownload(RunLastDownloadFinder());
287 }
288
289 // Tests that there is no crash if the finder is deleted before results arrive.
290 TEST_F(LastDownloadFinderTest, DeleteBeforeResults) {
291   // Create a profile with a history service that is opted-in.
292   TestingProfile* profile = CreateProfile(SAFE_BROWSING_OPT_IN);
293
294   // Add a download.
295   AddDownload(profile, CreateTestDownloadRow());
296
297   // Start a finder and kill it before the search completes.
298   safe_browsing::LastDownloadFinder::Create(
299       base::Bind(&LastDownloadFinderTest::NeverCalled, base::Unretained(this)))
300       .reset();
301
302   // Flush tasks on the history backend thread.
303   FlushHistoryBackend(profile);
304 }
305
306 // Tests that a download in profile added after the search is begun is found.
307 TEST_F(LastDownloadFinderTest, AddProfileAfterStarting) {
308   // Create a profile with a history service that is opted-in.
309   CreateProfile(SAFE_BROWSING_OPT_IN);
310
311   scoped_ptr<safe_browsing::ClientIncidentReport_DownloadDetails> last_download;
312   base::RunLoop run_loop;
313
314   // Post a task that will create a second profile once the main loop is run.
315   base::MessageLoop::current()->PostTask(
316       FROM_HERE,
317       base::Bind(&LastDownloadFinderTest::CreateProfileWithDownload,
318                  base::Unretained(this)));
319
320   // Create a finder that we expect will find a download in the second profile.
321   scoped_ptr<safe_browsing::LastDownloadFinder> finder(
322       safe_browsing::LastDownloadFinder::Create(
323           base::Bind(&LastDownloadFinderTest::OnLastDownload,
324                      base::Unretained(this),
325                      &last_download,
326                      run_loop.QuitClosure())));
327
328   run_loop.Run();
329
330   ExpectFoundTestDownload(last_download.Pass());
331 }