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 "base/base_paths.h"
6#include "base/bind.h"
7#include "base/command_line.h"
8#include "base/files/file_path.h"
9#include "base/files/file_util.h"
10#include "base/files/scoped_temp_dir.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/run_loop.h"
13#include "base/test/scoped_path_override.h"
14#include "chrome/browser/extensions/test_extension_system.h"
15#include "chrome/browser/media_galleries/media_folder_finder.h"
16#include "chrome/browser/media_galleries/media_galleries_preferences.h"
17#include "chrome/browser/media_galleries/media_galleries_preferences_factory.h"
18#include "chrome/browser/media_galleries/media_galleries_test_util.h"
19#include "chrome/browser/media_galleries/media_scan_manager.h"
20#include "chrome/browser/media_galleries/media_scan_manager_observer.h"
21#include "chrome/test/base/testing_profile.h"
22#include "components/storage_monitor/test_storage_monitor.h"
23#include "content/public/test/test_browser_thread_bundle.h"
24#include "extensions/browser/extension_system.h"
25#include "extensions/common/extension.h"
26#include "extensions/common/permissions/media_galleries_permission.h"
27#include "testing/gtest/include/gtest/gtest.h"
28
29#if defined(OS_CHROMEOS)
30#include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
31#include "chrome/browser/chromeos/settings/cros_settings.h"
32#include "chrome/browser/chromeos/settings/device_settings_service.h"
33#endif
34
35namespace {
36
37class MockMediaFolderFinder : MediaFolderFinder {
38 public:
39  typedef base::Callback<void(MediaFolderFinderResultsCallback)>
40      FindFoldersStartedCallback;
41
42  static MediaFolderFinder* CreateMockMediaFolderFinder(
43      const FindFoldersStartedCallback& started_callback,
44      const base::Closure destruction_callback,
45      const MediaFolderFinderResultsCallback& callback) {
46    return new MockMediaFolderFinder(started_callback, destruction_callback,
47                                     callback);
48  }
49
50  MockMediaFolderFinder(
51      const FindFoldersStartedCallback& started_callback,
52      const base::Closure destruction_callback,
53      const MediaFolderFinderResultsCallback& callback)
54      : MediaFolderFinder(callback),
55        started_callback_(started_callback),
56        destruction_callback_(destruction_callback),
57        callback_(callback) {
58  }
59  virtual ~MockMediaFolderFinder() {
60    destruction_callback_.Run();
61  }
62
63  virtual void StartScan() OVERRIDE {
64    started_callback_.Run(callback_);
65  }
66
67 private:
68  FindFoldersStartedCallback started_callback_;
69  base::Closure destruction_callback_;
70  MediaFolderFinderResultsCallback callback_;
71
72  DISALLOW_COPY_AND_ASSIGN(MockMediaFolderFinder);
73};
74
75}  // namespace
76
77class TestMediaScanManager : public MediaScanManager {
78 public:
79  typedef base::Callback<MediaFolderFinder*(
80      const MediaFolderFinder::MediaFolderFinderResultsCallback&)>
81          MediaFolderFinderFactory;
82
83  explicit TestMediaScanManager(const MediaFolderFinderFactory& factory) {
84    SetMediaFolderFinderFactory(factory);
85  }
86  virtual ~TestMediaScanManager() {}
87
88 private:
89  DISALLOW_COPY_AND_ASSIGN(TestMediaScanManager);
90};
91
92class MediaScanManagerTest : public MediaScanManagerObserver,
93                             public testing::Test {
94 public:
95  MediaScanManagerTest()
96      : find_folders_start_count_(0),
97        find_folders_destroy_count_(0),
98        find_folders_success_(false),
99        expected_gallery_count_(0),
100        profile_(new TestingProfile()) {}
101
102  virtual ~MediaScanManagerTest() {
103    EXPECT_EQ(find_folders_start_count_, find_folders_destroy_count_);
104  }
105
106  virtual void SetUp() OVERRIDE {
107    ASSERT_TRUE(storage_monitor::TestStorageMonitor::CreateAndInstall());
108
109    extensions::TestExtensionSystem* extension_system(
110        static_cast<extensions::TestExtensionSystem*>(
111            extensions::ExtensionSystem::Get(profile_.get())));
112    extension_system->CreateExtensionService(
113        CommandLine::ForCurrentProcess(), base::FilePath(), false);
114
115    gallery_prefs_ =
116        MediaGalleriesPreferencesFactory::GetForProfile(profile_.get());
117    base::RunLoop loop;
118    gallery_prefs_->EnsureInitialized(loop.QuitClosure());
119    loop.Run();
120
121    std::vector<std::string> read_permissions;
122    read_permissions.push_back(
123        extensions::MediaGalleriesPermission::kReadPermission);
124    extension_ = AddMediaGalleriesApp("read", read_permissions, profile_.get());
125
126    ASSERT_TRUE(test_results_dir_.CreateUniqueTempDir());
127
128    MockMediaFolderFinder::FindFoldersStartedCallback started_callback =
129        base::Bind(&MediaScanManagerTest::OnFindFoldersStarted,
130                   base::Unretained(this));
131    base::Closure destruction_callback =
132        base::Bind(&MediaScanManagerTest::OnFindFoldersDestroyed,
133                   base::Unretained(this));
134    TestMediaScanManager::MediaFolderFinderFactory factory =
135        base::Bind(&MockMediaFolderFinder::CreateMockMediaFolderFinder,
136                   started_callback, destruction_callback);
137    media_scan_manager_.reset(new TestMediaScanManager(factory));
138    media_scan_manager_->AddObserver(profile_.get(), this);
139  }
140
141  virtual void TearDown() OVERRIDE {
142    media_scan_manager_->RemoveObserver(profile_.get());
143    media_scan_manager_.reset();
144    storage_monitor::TestStorageMonitor::Destroy();
145  }
146
147  // Create a test folder in the test specific scoped temp dir and return the
148  // final path in |full_path|.
149  void MakeTestFolder(const std::string& root_relative_path,
150                      base::FilePath* full_path) {
151    ASSERT_TRUE(test_results_dir_.IsValid());
152    *full_path =
153        test_results_dir_.path().AppendASCII(root_relative_path);
154    ASSERT_TRUE(base::CreateDirectory(*full_path));
155  }
156
157  // Create the specified path, and add it to preferences as a gallery.
158  MediaGalleryPrefId AddGallery(const std::string& rel_path,
159                                MediaGalleryPrefInfo::Type type,
160                                int audio_count,
161                                int image_count,
162                                int video_count) {
163    base::FilePath full_path;
164    MakeTestFolder(rel_path, &full_path);
165    MediaGalleryPrefInfo gallery_info;
166    gallery_prefs_->LookUpGalleryByPath(full_path, &gallery_info);
167    return gallery_prefs_->AddGallery(gallery_info.device_id,
168                                      gallery_info.path,
169                                      type,
170                                      gallery_info.volume_label,
171                                      gallery_info.vendor_name,
172                                      gallery_info.model_name,
173                                      gallery_info.total_size_in_bytes,
174                                      gallery_info.last_attach_time,
175                                      audio_count, image_count, video_count);
176  }
177
178  void SetFindFoldersResults(
179      bool success,
180      const MediaFolderFinder::MediaFolderFinderResults& results) {
181    find_folders_success_ = success;
182    find_folders_results_ = results;
183  }
184
185  void SetExpectedScanResults(int gallery_count,
186                               const MediaGalleryScanResult& file_counts) {
187    expected_gallery_count_ = gallery_count;
188    expected_file_counts_ = file_counts;
189  }
190
191  void StartScan() {
192    media_scan_manager_->StartScan(
193        profile_.get(), extension_.get(), true /* user_gesture */);
194  }
195
196  MediaGalleriesPreferences* gallery_prefs() {
197    return gallery_prefs_;
198  }
199
200  const MediaGalleriesPrefInfoMap& known_galleries() const {
201    return gallery_prefs_->known_galleries();
202  }
203
204  size_t gallery_count() const {
205    return known_galleries().size();
206  }
207
208  extensions::Extension* extension() {
209    return extension_.get();
210  }
211
212  int FindFoldersStartCount() {
213    return find_folders_start_count_;
214  }
215
216  int FindFolderDestroyCount() {
217    return find_folders_destroy_count_;
218  }
219
220  void CheckFileCounts(MediaGalleryPrefId pref_id, int audio_count,
221                       int image_count, int video_count) {
222    if (!ContainsKey(known_galleries(), pref_id)) {
223      EXPECT_TRUE(false);
224      return;
225    }
226    MediaGalleriesPrefInfoMap::const_iterator pref_info =
227        known_galleries().find(pref_id);
228    EXPECT_EQ(audio_count, pref_info->second.audio_count);
229    EXPECT_EQ(image_count, pref_info->second.image_count);
230    EXPECT_EQ(video_count, pref_info->second.video_count);
231  }
232
233  // MediaScanManagerObserver implementation.
234  virtual void OnScanFinished(
235      const std::string& extension_id,
236      int gallery_count,
237      const MediaGalleryScanResult& file_counts) OVERRIDE {
238    EXPECT_EQ(extension_->id(), extension_id);
239    EXPECT_EQ(expected_gallery_count_, gallery_count);
240    EXPECT_EQ(expected_file_counts_.audio_count, file_counts.audio_count);
241    EXPECT_EQ(expected_file_counts_.image_count, file_counts.image_count);
242    EXPECT_EQ(expected_file_counts_.video_count, file_counts.video_count);
243  }
244
245 protected:
246  // So derived tests can access ...::FindContainerScanResults().
247  MediaFolderFinder::MediaFolderFinderResults FindContainerScanResults(
248      const MediaFolderFinder::MediaFolderFinderResults& found_folders,
249      const std::vector<base::FilePath>& sensitive_locations) {
250    return MediaScanManager::FindContainerScanResults(found_folders,
251                                                      sensitive_locations);
252  }
253
254 private:
255  void OnFindFoldersStarted(
256      MediaFolderFinder::MediaFolderFinderResultsCallback callback) {
257    find_folders_start_count_++;
258    callback.Run(find_folders_success_, find_folders_results_);
259  }
260
261  void OnFindFoldersDestroyed() {
262    find_folders_destroy_count_++;
263  }
264
265  scoped_ptr<TestMediaScanManager> media_scan_manager_;
266
267  int find_folders_start_count_;
268  int find_folders_destroy_count_;
269  bool find_folders_success_;
270  MediaFolderFinder::MediaFolderFinderResults find_folders_results_;
271
272  int expected_gallery_count_;
273  MediaGalleryScanResult expected_file_counts_;
274
275  base::ScopedTempDir test_results_dir_;
276
277  // Needed for extension service & friends to work.
278  content::TestBrowserThreadBundle thread_bundle_;
279
280  scoped_refptr<extensions::Extension> extension_;
281
282  EnsureMediaDirectoriesExists mock_gallery_locations_;
283
284#if defined(OS_CHROMEOS)
285  chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
286  chromeos::ScopedTestCrosSettings test_cros_settings_;
287  chromeos::ScopedTestUserManager test_user_manager_;
288#endif
289
290  storage_monitor::TestStorageMonitor monitor_;
291  scoped_ptr<TestingProfile> profile_;
292  MediaGalleriesPreferences* gallery_prefs_;
293
294  DISALLOW_COPY_AND_ASSIGN(MediaScanManagerTest);
295};
296
297TEST_F(MediaScanManagerTest, SingleResult) {
298  size_t galleries_before = gallery_count();
299  MediaGalleryScanResult file_counts;
300  file_counts.audio_count = 1;
301  file_counts.image_count = 2;
302  file_counts.video_count = 3;
303  base::FilePath path;
304  MakeTestFolder("found_media_folder", &path);
305
306  MediaFolderFinder::MediaFolderFinderResults found_folders;
307  found_folders[path] = file_counts;
308  SetFindFoldersResults(true, found_folders);
309
310  SetExpectedScanResults(1 /*gallery_count*/, file_counts);
311  StartScan();
312
313  base::RunLoop().RunUntilIdle();
314  EXPECT_EQ(1, FindFolderDestroyCount());
315  EXPECT_EQ(galleries_before + 1, gallery_count());
316}
317
318// Generally test that it includes directories with sufficient density
319// and excludes others.
320//
321// A/ - NOT included
322// A/B/ - NOT included
323// A/B/C/files
324// A/D/ - NOT included
325// A/D/E/files
326// A/D/F/files
327// A/D/G/files
328// A/D/H/
329// A/H/ - included in results
330// A/H/I/files
331// A/H/J/files
332TEST_F(MediaScanManagerTest, MergeRedundant) {
333  base::FilePath path;
334  MediaFolderFinder::MediaFolderFinderResults found_folders;
335  std::vector<base::FilePath> sensitive_locations;
336  std::vector<base::FilePath> expected_folders;
337  MediaGalleryScanResult file_counts;
338  file_counts.audio_count = 1;
339  file_counts.image_count = 2;
340  file_counts.video_count = 3;
341  MakeTestFolder("A", &path);
342  MakeTestFolder("A/B", &path);
343  MakeTestFolder("A/B/C", &path);
344  found_folders[path] = file_counts;
345  // Not dense enough.
346  MakeTestFolder("A/D", &path);
347  MakeTestFolder("A/D/E", &path);
348  found_folders[path] = file_counts;
349  MakeTestFolder("A/D/F", &path);
350  found_folders[path] = file_counts;
351  MakeTestFolder("A/D/G", &path);
352  found_folders[path] = file_counts;
353  MakeTestFolder("A/D/H", &path);
354  // Dense enough to be reported.
355  MakeTestFolder("A/H", &path);
356  expected_folders.push_back(path);
357  MakeTestFolder("A/H/I", &path);
358  found_folders[path] = file_counts;
359  MakeTestFolder("A/H/J", &path);
360  found_folders[path] = file_counts;
361  MediaFolderFinder::MediaFolderFinderResults results =
362      FindContainerScanResults(found_folders, sensitive_locations);
363  EXPECT_EQ(expected_folders.size(), results.size());
364  for (std::vector<base::FilePath>::const_iterator it =
365           expected_folders.begin();
366       it != expected_folders.end();
367       ++it) {
368    EXPECT_TRUE(results.find(*it) != results.end());
369  }
370}
371
372// Make sure intermediates are not included.
373//
374// A/ - included in results
375// A/B1/ - NOT included
376// A/B1/B2/files
377// A/C1/ - NOT included
378// A/C1/C2/files
379TEST_F(MediaScanManagerTest, MergeRedundantNoIntermediates) {
380  base::FilePath path;
381  MediaFolderFinder::MediaFolderFinderResults found_folders;
382  std::vector<base::FilePath> sensitive_locations;
383  std::vector<base::FilePath> expected_folders;
384  MediaGalleryScanResult file_counts;
385  file_counts.audio_count = 1;
386  file_counts.image_count = 2;
387  file_counts.video_count = 3;
388  MakeTestFolder("A", &path);
389  expected_folders.push_back(path);
390  MakeTestFolder("A/B1", &path);
391  MakeTestFolder("A/B1/B2", &path);
392  found_folders[path] = file_counts;
393  MakeTestFolder("A/C1", &path);
394  MakeTestFolder("A/C1/C2", &path);
395  found_folders[path] = file_counts;
396  // Make "home dir" not dense enough.
397  MakeTestFolder("D", &path);
398  MediaFolderFinder::MediaFolderFinderResults results =
399      FindContainerScanResults(found_folders, sensitive_locations);
400  EXPECT_EQ(expected_folders.size(), results.size());
401  for (std::vector<base::FilePath>::const_iterator it =
402           expected_folders.begin();
403       it != expected_folders.end();
404       ++it) {
405    EXPECT_TRUE(results.find(*it) != results.end());
406  }
407}
408
409// Make sure "A/" only gets a count of 1, from "A/D/",
410// not 2 from "A/D/H/" and "A/D/I/".
411//
412// A/ - NOT included
413// A/D/ - included in results
414// A/D/E/files
415// A/D/F/files
416// A/D/G/files
417// A/D/H/files
418// A/D/I/ - NOT included
419// A/D/I/J/files
420TEST_F(MediaScanManagerTest, MergeRedundantVerifyNoOvercount) {
421  base::FilePath path;
422  MediaFolderFinder::MediaFolderFinderResults found_folders;
423  std::vector<base::FilePath> sensitive_locations;
424  std::vector<base::FilePath> expected_folders;
425  MediaGalleryScanResult file_counts;
426  file_counts.audio_count = 1;
427  file_counts.image_count = 2;
428  file_counts.video_count = 3;
429  MakeTestFolder("A", &path);
430  MakeTestFolder("A/D", &path);
431  expected_folders.push_back(path);
432  MakeTestFolder("A/D/E", &path);
433  found_folders[path] = file_counts;
434  MakeTestFolder("A/D/F", &path);
435  found_folders[path] = file_counts;
436  MakeTestFolder("A/D/G", &path);
437  found_folders[path] = file_counts;
438  MakeTestFolder("A/D/H", &path);
439  found_folders[path] = file_counts;
440  MakeTestFolder("A/D/I", &path);
441  MakeTestFolder("A/D/I/J", &path);
442  found_folders[path] = file_counts;
443  MediaFolderFinder::MediaFolderFinderResults results =
444      FindContainerScanResults(found_folders, sensitive_locations);
445  EXPECT_EQ(expected_folders.size(), results.size());
446  for (std::vector<base::FilePath>::const_iterator it =
447           expected_folders.begin();
448       it != expected_folders.end();
449       ++it) {
450    EXPECT_TRUE(results.find(*it) != results.end());
451  }
452}
453
454// Make sure that sensistive directories are pruned.
455//
456// A/ - NOT included
457// A/B/ - sensitive
458// A/C/ - included in results
459// A/C/G/files
460// A/C/H/files
461// A/D/ - included in results
462// A/D/I/files
463// A/D/J/files
464// A/E/ - included in results
465// A/E/K/files
466// A/E/L/files
467// A/F/ - included in results
468// A/F/M/files
469// A/F/N/files
470TEST_F(MediaScanManagerTest, MergeRedundantWithSensitive) {
471  base::FilePath path;
472  MediaFolderFinder::MediaFolderFinderResults found_folders;
473  std::vector<base::FilePath> sensitive_locations;
474  std::vector<base::FilePath> expected_folders;
475  MediaGalleryScanResult file_counts;
476  file_counts.audio_count = 1;
477  file_counts.image_count = 2;
478  file_counts.video_count = 3;
479  MakeTestFolder("A", &path);
480  MakeTestFolder("A/B", &path);
481  sensitive_locations.push_back(path);
482  MakeTestFolder("A/C", &path);
483  expected_folders.push_back(path);
484  MakeTestFolder("A/C/G", &path);
485  found_folders[path] = file_counts;
486  MakeTestFolder("A/C/H", &path);
487  found_folders[path] = file_counts;
488  MakeTestFolder("A/D", &path);
489  expected_folders.push_back(path);
490  MakeTestFolder("A/D/I", &path);
491  found_folders[path] = file_counts;
492  MakeTestFolder("A/D/J", &path);
493  found_folders[path] = file_counts;
494  MakeTestFolder("A/E", &path);
495  expected_folders.push_back(path);
496  MakeTestFolder("A/E/K", &path);
497  found_folders[path] = file_counts;
498  MakeTestFolder("A/E/L", &path);
499  found_folders[path] = file_counts;
500  MakeTestFolder("A/F", &path);
501  expected_folders.push_back(path);
502  MakeTestFolder("A/F/M", &path);
503  found_folders[path] = file_counts;
504  MakeTestFolder("A/F/N", &path);
505  found_folders[path] = file_counts;
506  MediaFolderFinder::MediaFolderFinderResults results =
507      FindContainerScanResults(found_folders, sensitive_locations);
508  EXPECT_EQ(expected_folders.size(), results.size());
509  for (std::vector<base::FilePath>::const_iterator it =
510           expected_folders.begin();
511       it != expected_folders.end();
512       ++it) {
513    EXPECT_TRUE(results.find(*it) != results.end());
514  }
515}
516
517TEST_F(MediaScanManagerTest, Containers) {
518  MediaGalleryScanResult file_counts;
519  file_counts.audio_count = 1;
520  base::FilePath path;
521  std::set<base::FilePath> expected_galleries;
522  std::set<base::FilePath> bad_galleries;
523  MediaFolderFinder::MediaFolderFinderResults found_folders;
524  size_t galleries_before = gallery_count();
525
526  // Should manifest as a gallery in result1.
527  MakeTestFolder("dir1/result1", &path);
528  expected_galleries.insert(path);
529  found_folders[path] = file_counts;
530
531  // Should manifest as a gallery in dir2.
532  MakeTestFolder("dir2/result2", &path);
533  bad_galleries.insert(path);
534  found_folders[path] = file_counts;
535  MakeTestFolder("dir2/result3", &path);
536  bad_galleries.insert(path);
537  found_folders[path] = file_counts;
538  expected_galleries.insert(path.DirName());
539
540  // Should manifest as a two galleries: result4 and result5.
541  MakeTestFolder("dir3/other", &path);
542  bad_galleries.insert(path);
543  MakeTestFolder("dir3/result4", &path);
544  expected_galleries.insert(path);
545  found_folders[path] = file_counts;
546  MakeTestFolder("dir3/result5", &path);
547  expected_galleries.insert(path);
548  found_folders[path] = file_counts;
549
550  // Should manifest as a gallery in dir4.
551  MakeTestFolder("dir4/other", &path);
552  bad_galleries.insert(path);
553  MakeTestFolder("dir4/result6", &path);
554  bad_galleries.insert(path);
555  found_folders[path] = file_counts;
556  MakeTestFolder("dir4/result7", &path);
557  bad_galleries.insert(path);
558  found_folders[path] = file_counts;
559  MakeTestFolder("dir4/result8", &path);
560  bad_galleries.insert(path);
561  found_folders[path] = file_counts;
562  MakeTestFolder("dir4/result9", &path);
563  bad_galleries.insert(path);
564  found_folders[path] = file_counts;
565  expected_galleries.insert(path.DirName());
566
567  SetFindFoldersResults(true, found_folders);
568
569  file_counts.audio_count = 9;
570  SetExpectedScanResults(5 /*gallery_count*/, file_counts);
571  StartScan();
572
573  base::RunLoop().RunUntilIdle();
574  EXPECT_EQ(1, FindFolderDestroyCount());
575  EXPECT_EQ(galleries_before + 5, gallery_count());
576
577  std::set<base::FilePath> found_galleries;
578  for (MediaGalleriesPrefInfoMap::const_iterator it = known_galleries().begin();
579       it != known_galleries().end();
580       ++it) {
581    found_galleries.insert(it->second.AbsolutePath());
582    DCHECK(!ContainsKey(bad_galleries, it->second.AbsolutePath()));
583  }
584  for (std::set<base::FilePath>::const_iterator it = expected_galleries.begin();
585       it != expected_galleries.end();
586       ++it) {
587    DCHECK(ContainsKey(found_galleries, *it));
588  }
589}
590
591TEST_F(MediaScanManagerTest, UpdateExistingScanResults) {
592  size_t galleries_before = gallery_count();
593
594  MediaGalleryPrefId ungranted_scan =
595      AddGallery("uscan", MediaGalleryPrefInfo::kScanResult, 1, 0, 0);
596  MediaGalleryPrefId granted_scan =
597      AddGallery("gscan", MediaGalleryPrefInfo::kScanResult, 0, 2, 0);
598  gallery_prefs()->SetGalleryPermissionForExtension(*extension(), granted_scan,
599                                                    true);
600  EXPECT_EQ(galleries_before + 2, gallery_count());
601
602  // Run once with no scan results. "uscan" should go away and "gscan" should
603  // have its scan counts updated.
604  MediaFolderFinder::MediaFolderFinderResults found_folders;
605  SetFindFoldersResults(true, found_folders);
606
607  MediaGalleryScanResult file_counts;
608  SetExpectedScanResults(0 /*gallery_count*/, file_counts);
609  StartScan();
610
611  base::RunLoop().RunUntilIdle();
612  EXPECT_EQ(1, FindFolderDestroyCount());
613  EXPECT_EQ(galleries_before + 1, gallery_count());
614  CheckFileCounts(granted_scan, 0, 0, 0);
615
616  MediaGalleryPrefId id =
617      AddGallery("uscan", MediaGalleryPrefInfo::kScanResult, 1, 1, 1);
618  EXPECT_NE(id, ungranted_scan);
619  ungranted_scan = id;
620
621  // Add scan results near the existing scan results.
622  file_counts.audio_count = 0;
623  file_counts.image_count = 0;
624  file_counts.video_count = 7;
625  base::FilePath path;
626  MakeTestFolder("uscan", &path);
627  found_folders[path] = file_counts;
628
629  file_counts.video_count = 11;
630  MakeTestFolder("gscan/dir1", &path);
631  found_folders[path] = file_counts;
632
633  MakeTestFolder("junk", &path);
634
635  SetFindFoldersResults(true, found_folders);
636  file_counts.video_count = 7;
637  SetExpectedScanResults(1 /*gallery_count*/, file_counts);
638  StartScan();
639
640  base::RunLoop().RunUntilIdle();
641  EXPECT_EQ(2, FindFolderDestroyCount());
642  EXPECT_EQ(galleries_before + 2, gallery_count());
643  CheckFileCounts(granted_scan, 0, 0, 11);
644  // The new scan result should be one more than it's previous id.
645  CheckFileCounts(ungranted_scan + 1, 0, 0, 7);
646}
647
648TEST_F(MediaScanManagerTest, UpdateExistingCounts) {
649  size_t galleries_before = gallery_count();
650
651  MediaGalleryPrefId auto_id =
652      AddGallery("auto", MediaGalleryPrefInfo::kAutoDetected, 1, 0, 0);
653  MediaGalleryPrefId user_id =
654      AddGallery("user", MediaGalleryPrefInfo::kUserAdded, 0, 2, 0);
655  MediaGalleryPrefId scan_id =
656      AddGallery("scan", MediaGalleryPrefInfo::kScanResult, 0, 0, 3);
657  // Grant permission so this one isn't removed and readded.
658  gallery_prefs()->SetGalleryPermissionForExtension(*extension(), scan_id,
659                                                    true);
660  CheckFileCounts(auto_id, 1, 0, 0);
661  CheckFileCounts(user_id, 0, 2, 0);
662  CheckFileCounts(scan_id, 0, 0, 3);
663
664  MediaFolderFinder::MediaFolderFinderResults found_folders;
665  MediaGalleryScanResult file_counts;
666  file_counts.audio_count = 4;
667  base::FilePath path;
668  MakeTestFolder("auto/dir1", &path);
669  found_folders[path] = file_counts;
670
671  file_counts.audio_count = 6;
672  MakeTestFolder("scan", &path);
673  found_folders[path] = file_counts;
674
675  MakeTestFolder("junk", &path);
676
677  file_counts.audio_count = 5;
678  MakeTestFolder("user/dir2", &path);
679  found_folders[path] = file_counts;
680
681  SetFindFoldersResults(true, found_folders);
682
683  file_counts.audio_count = 0;
684  SetExpectedScanResults(0 /*gallery_count*/, file_counts);
685  StartScan();
686
687  base::RunLoop().RunUntilIdle();
688  EXPECT_EQ(1, FindFolderDestroyCount());
689  EXPECT_EQ(galleries_before + 3, gallery_count());
690  CheckFileCounts(auto_id, 4, 0, 0);
691  CheckFileCounts(user_id, 5, 0, 0);
692  CheckFileCounts(scan_id, 6, 0, 0);
693
694  EXPECT_EQ(1U, found_folders.erase(path));
695  SetFindFoldersResults(true, found_folders);
696  SetExpectedScanResults(0 /*gallery_count*/, file_counts);
697  StartScan();
698
699  base::RunLoop().RunUntilIdle();
700  EXPECT_EQ(2, FindFolderDestroyCount());
701  EXPECT_EQ(galleries_before + 3, gallery_count());
702  CheckFileCounts(auto_id, 4, 0, 0);
703  CheckFileCounts(user_id, 0, 0, 0);
704  CheckFileCounts(scan_id, 6, 0, 0);
705}
706
707TEST_F(MediaScanManagerTest, Graylist) {
708  size_t galleries_before = gallery_count();
709  MediaGalleryScanResult file_counts;
710  file_counts.audio_count = 1;
711  file_counts.image_count = 2;
712  file_counts.video_count = 3;
713  base::FilePath path;
714  MakeTestFolder("found_media_folder", &path);
715  base::ScopedPathOverride scoped_fake_home_dir_override(base::DIR_HOME, path);
716
717  const size_t kGalleriesAdded = 3;
718  MediaFolderFinder::MediaFolderFinderResults found_folders;
719  MakeTestFolder("found_media_folder/dir1", &path);
720  found_folders[path] = file_counts;
721  MakeTestFolder("found_media_folder/dir2", &path);
722  found_folders[path] = file_counts;
723  MakeTestFolder("found_media_folder/dir3", &path);
724  found_folders[path] = file_counts;
725  SetFindFoldersResults(true, found_folders);
726
727  file_counts.audio_count *= kGalleriesAdded;
728  file_counts.image_count *= kGalleriesAdded;
729  file_counts.video_count *= kGalleriesAdded;
730  SetExpectedScanResults(kGalleriesAdded, file_counts);
731  StartScan();
732
733  base::RunLoop().RunUntilIdle();
734  EXPECT_EQ(1, FindFolderDestroyCount());
735  EXPECT_EQ(galleries_before + kGalleriesAdded, gallery_count());
736}
737