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.
6 #include "base/command_line.h"
7 #include "base/file_util.h"
8 #include "base/files/file_path.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/run_loop.h"
12 #include "chrome/browser/extensions/test_extension_system.h"
13 #include "chrome/browser/media_galleries/media_folder_finder.h"
14 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
15 #include "chrome/browser/media_galleries/media_galleries_preferences_factory.h"
16 #include "chrome/browser/media_galleries/media_galleries_test_util.h"
17 #include "chrome/browser/media_galleries/media_scan_manager.h"
18 #include "chrome/browser/media_galleries/media_scan_manager_observer.h"
19 #include "chrome/browser/storage_monitor/test_storage_monitor.h"
20 #include "chrome/common/extensions/permissions/media_galleries_permission.h"
21 #include "chrome/test/base/testing_profile.h"
22 #include "content/public/test/test_browser_thread_bundle.h"
23 #include "extensions/browser/extension_system.h"
24 #include "extensions/common/extension.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 #if defined(OS_CHROMEOS)
28 #include "chrome/browser/chromeos/login/user_manager.h"
29 #include "chrome/browser/chromeos/settings/cros_settings.h"
30 #include "chrome/browser/chromeos/settings/device_settings_service.h"
35 class MockMediaFolderFinder
: MediaFolderFinder
{
37 typedef base::Callback
<void(MediaFolderFinderResultsCallback
)>
38 FindFoldersStartedCallback
;
40 static MediaFolderFinder
* CreateMockMediaFolderFinder(
41 const FindFoldersStartedCallback
& started_callback
,
42 const base::Closure destruction_callback
,
43 const MediaFolderFinderResultsCallback
& callback
) {
44 return new MockMediaFolderFinder(started_callback
, destruction_callback
,
48 MockMediaFolderFinder(
49 const FindFoldersStartedCallback
& started_callback
,
50 const base::Closure destruction_callback
,
51 const MediaFolderFinderResultsCallback
& callback
)
52 : MediaFolderFinder(callback
),
53 started_callback_(started_callback
),
54 destruction_callback_(destruction_callback
),
57 virtual ~MockMediaFolderFinder() {
58 destruction_callback_
.Run();
61 virtual void StartScan() OVERRIDE
{
62 started_callback_
.Run(callback_
);
66 FindFoldersStartedCallback started_callback_
;
67 base::Closure destruction_callback_
;
68 MediaFolderFinderResultsCallback callback_
;
70 DISALLOW_COPY_AND_ASSIGN(MockMediaFolderFinder
);
75 class TestMediaScanManager
: public MediaScanManager
{
77 typedef base::Callback
<MediaFolderFinder
*(
78 const MediaFolderFinder::MediaFolderFinderResultsCallback
&)>
79 MediaFolderFinderFactory
;
81 explicit TestMediaScanManager(const MediaFolderFinderFactory
& factory
) {
82 SetMediaFolderFinderFactory(factory
);
84 virtual ~TestMediaScanManager() {}
87 DISALLOW_COPY_AND_ASSIGN(TestMediaScanManager
);
90 class MediaScanManagerTest
: public MediaScanManagerObserver
,
91 public testing::Test
{
93 MediaScanManagerTest()
94 : find_folders_start_count_(0),
95 find_folders_destroy_count_(0),
96 find_folders_success_(false),
97 expected_gallery_count_(0),
98 profile_(new TestingProfile()) {}
100 virtual ~MediaScanManagerTest() {
101 EXPECT_EQ(find_folders_start_count_
, find_folders_destroy_count_
);
104 virtual void SetUp() OVERRIDE
{
105 ASSERT_TRUE(TestStorageMonitor::CreateAndInstall());
107 extensions::TestExtensionSystem
* extension_system(
108 static_cast<extensions::TestExtensionSystem
*>(
109 extensions::ExtensionSystem::Get(profile_
.get())));
110 extension_system
->CreateExtensionService(
111 CommandLine::ForCurrentProcess(), base::FilePath(), false);
114 MediaGalleriesPreferencesFactory::GetForProfile(profile_
.get());
116 gallery_prefs_
->EnsureInitialized(loop
.QuitClosure());
119 std::vector
<std::string
> read_permissions
;
120 read_permissions
.push_back(
121 extensions::MediaGalleriesPermission::kReadPermission
);
122 extension_
= AddMediaGalleriesApp("read", read_permissions
, profile_
.get());
124 ASSERT_TRUE(test_results_dir_
.CreateUniqueTempDir());
126 MockMediaFolderFinder::FindFoldersStartedCallback started_callback
=
127 base::Bind(&MediaScanManagerTest::OnFindFoldersStarted
,
128 base::Unretained(this));
129 base::Closure destruction_callback
=
130 base::Bind(&MediaScanManagerTest::OnFindFoldersDestroyed
,
131 base::Unretained(this));
132 TestMediaScanManager::MediaFolderFinderFactory factory
=
133 base::Bind(&MockMediaFolderFinder::CreateMockMediaFolderFinder
,
134 started_callback
, destruction_callback
);
135 media_scan_manager_
.reset(new TestMediaScanManager(factory
));
136 media_scan_manager_
->AddObserver(profile_
.get(), this);
139 virtual void TearDown() OVERRIDE
{
140 media_scan_manager_
->RemoveObserver(profile_
.get());
141 media_scan_manager_
.reset();
142 TestStorageMonitor::RemoveSingleton();
145 // Create a test folder in the test specific scoped temp dir and return the
147 base::FilePath
MakeTestFolder(const std::string
& root_relative_path
) {
148 DCHECK(test_results_dir_
.IsValid());
149 base::FilePath path
=
150 test_results_dir_
.path().AppendASCII(root_relative_path
);
151 if (!base::CreateDirectory(path
)) {
152 return base::FilePath();
157 // Create the specified path, and add it to preferences as a gallery.
158 MediaGalleryPrefId
AddGallery(const std::string
& path
,
159 MediaGalleryPrefInfo::Type type
,
163 base::FilePath full_path
= MakeTestFolder(path
);
164 if (full_path
.empty())
165 return kInvalidMediaGalleryPrefId
;
166 MediaGalleryPrefInfo gallery_info
;
167 gallery_prefs_
->LookUpGalleryByPath(full_path
, &gallery_info
);
168 return gallery_prefs_
->AddGallery(gallery_info
.device_id
,
171 gallery_info
.volume_label
,
172 gallery_info
.vendor_name
,
173 gallery_info
.model_name
,
174 gallery_info
.total_size_in_bytes
,
175 gallery_info
.last_attach_time
,
176 audio_count
, image_count
, video_count
);
179 void SetFindFoldersResults(
181 const MediaFolderFinder::MediaFolderFinderResults
& results
) {
182 find_folders_success_
= success
;
183 find_folders_results_
= results
;
186 void SetExpectedScanResults(int gallery_count
,
187 const MediaGalleryScanResult
& file_counts
) {
188 expected_gallery_count_
= gallery_count
;
189 expected_file_counts_
= file_counts
;
193 media_scan_manager_
->StartScan(profile_
.get(), extension_
,
194 true /* user_gesture */);
197 MediaGalleriesPreferences
* gallery_prefs() {
198 return gallery_prefs_
;
201 extensions::Extension
* extension() {
202 return extension_
.get();
205 int FindFoldersStartCount() {
206 return find_folders_start_count_
;
209 int FindFolderDestroyCount() {
210 return find_folders_destroy_count_
;
213 void CheckFileCounts(MediaGalleryPrefId pref_id
, int audio_count
,
214 int image_count
, int video_count
) {
215 if (!ContainsKey(gallery_prefs_
->known_galleries(), pref_id
)) {
219 MediaGalleriesPrefInfoMap::const_iterator pref_info
=
220 gallery_prefs_
->known_galleries().find(pref_id
);
221 EXPECT_EQ(audio_count
, pref_info
->second
.audio_count
);
222 EXPECT_EQ(image_count
, pref_info
->second
.image_count
);
223 EXPECT_EQ(video_count
, pref_info
->second
.video_count
);
226 // MediaScanMangerObserver implementation.
227 virtual void OnScanFinished(
228 const std::string
& extension_id
,
230 const MediaGalleryScanResult
& file_counts
) OVERRIDE
{
231 EXPECT_EQ(extension_
->id(), extension_id
);
232 EXPECT_EQ(expected_gallery_count_
, gallery_count
);
233 EXPECT_EQ(expected_file_counts_
.audio_count
, file_counts
.audio_count
);
234 EXPECT_EQ(expected_file_counts_
.image_count
, file_counts
.image_count
);
235 EXPECT_EQ(expected_file_counts_
.video_count
, file_counts
.video_count
);
239 void OnFindFoldersStarted(
240 MediaFolderFinder::MediaFolderFinderResultsCallback callback
) {
241 find_folders_start_count_
++;
242 callback
.Run(find_folders_success_
, find_folders_results_
);
245 void OnFindFoldersDestroyed() {
246 find_folders_destroy_count_
++;
249 scoped_ptr
<TestMediaScanManager
> media_scan_manager_
;
251 int find_folders_start_count_
;
252 int find_folders_destroy_count_
;
253 bool find_folders_success_
;
254 MediaFolderFinder::MediaFolderFinderResults find_folders_results_
;
256 int expected_gallery_count_
;
257 MediaGalleryScanResult expected_file_counts_
;
259 base::ScopedTempDir test_results_dir_
;
261 // Needed for extension service & friends to work.
262 content::TestBrowserThreadBundle thread_bundle_
;
264 scoped_refptr
<extensions::Extension
> extension_
;
266 EnsureMediaDirectoriesExists mock_gallery_locations_
;
268 #if defined(OS_CHROMEOS)
269 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_
;
270 chromeos::ScopedTestCrosSettings test_cros_settings_
;
271 chromeos::ScopedTestUserManager test_user_manager_
;
274 TestStorageMonitor monitor_
;
275 scoped_ptr
<TestingProfile
> profile_
;
276 MediaGalleriesPreferences
* gallery_prefs_
;
278 DISALLOW_COPY_AND_ASSIGN(MediaScanManagerTest
);
281 TEST_F(MediaScanManagerTest
, SingleResult
) {
282 size_t galleries_before
= gallery_prefs()->known_galleries().size();
283 MediaGalleryScanResult file_counts
;
284 file_counts
.audio_count
= 1;
285 file_counts
.image_count
= 2;
286 file_counts
.video_count
= 3;
287 base::FilePath path
= MakeTestFolder("found_media_folder");
289 MediaFolderFinder::MediaFolderFinderResults found_folders
;
290 found_folders
[path
] = file_counts
;
291 SetFindFoldersResults(true, found_folders
);
293 SetExpectedScanResults(1 /*gallery_count*/, file_counts
);
296 base::RunLoop().RunUntilIdle();
297 EXPECT_EQ(1, FindFolderDestroyCount());
298 EXPECT_EQ(galleries_before
+ 1, gallery_prefs()->known_galleries().size());
301 TEST_F(MediaScanManagerTest
, Containers
) {
302 MediaGalleryScanResult file_counts
;
303 file_counts
.audio_count
= 1;
305 std::set
<base::FilePath
> expected_galleries
;
306 std::set
<base::FilePath
> bad_galleries
;
307 MediaFolderFinder::MediaFolderFinderResults found_folders
;
308 size_t galleries_before
= gallery_prefs()->known_galleries().size();
310 // Should manifest as a gallery in result1.
311 path
= MakeTestFolder("dir1/result1");
312 expected_galleries
.insert(path
);
313 found_folders
[path
] = file_counts
;
315 // Should manifest as a gallery in dir2.
316 path
= MakeTestFolder("dir2/result2");
317 bad_galleries
.insert(path
);
318 found_folders
[path
] = file_counts
;
319 path
= MakeTestFolder("dir2/result3");
320 bad_galleries
.insert(path
);
321 found_folders
[path
] = file_counts
;
322 expected_galleries
.insert(path
.DirName());
324 // Should manifest as a two galleries: result4 and result5.
325 path
= MakeTestFolder("dir3/other");
326 bad_galleries
.insert(path
);
327 path
= MakeTestFolder("dir3/result4");
328 expected_galleries
.insert(path
);
329 found_folders
[path
] = file_counts
;
330 path
= MakeTestFolder("dir3/result5");
331 expected_galleries
.insert(path
);
332 found_folders
[path
] = file_counts
;
334 // Should manifest as a gallery in dir4.
335 path
= MakeTestFolder("dir4/other");
336 bad_galleries
.insert(path
);
337 path
= MakeTestFolder("dir4/result6");
338 bad_galleries
.insert(path
);
339 found_folders
[path
] = file_counts
;
340 path
= MakeTestFolder("dir4/result7");
341 bad_galleries
.insert(path
);
342 found_folders
[path
] = file_counts
;
343 path
= MakeTestFolder("dir4/result8");
344 bad_galleries
.insert(path
);
345 found_folders
[path
] = file_counts
;
346 path
= MakeTestFolder("dir4/result9");
347 bad_galleries
.insert(path
);
348 found_folders
[path
] = file_counts
;
349 expected_galleries
.insert(path
.DirName());
351 SetFindFoldersResults(true, found_folders
);
353 file_counts
.audio_count
= 9;
354 SetExpectedScanResults(5 /*gallery_count*/, file_counts
);
357 base::RunLoop().RunUntilIdle();
358 EXPECT_EQ(1, FindFolderDestroyCount());
359 EXPECT_EQ(galleries_before
+ 5, gallery_prefs()->known_galleries().size());
361 std::set
<base::FilePath
> found_galleries
;
362 for (MediaGalleriesPrefInfoMap::const_iterator it
=
363 gallery_prefs()->known_galleries().begin();
364 it
!= gallery_prefs()->known_galleries().end();
366 found_galleries
.insert(it
->second
.AbsolutePath());
367 DCHECK(!ContainsKey(bad_galleries
, it
->second
.AbsolutePath()));
369 for (std::set
<base::FilePath
>::const_iterator it
= expected_galleries
.begin();
370 it
!= expected_galleries
.end();
372 DCHECK(ContainsKey(found_galleries
, *it
));
376 TEST_F(MediaScanManagerTest
, UpdateExistingScanResults
) {
377 size_t galleries_before
= gallery_prefs()->known_galleries().size();
379 MediaGalleryPrefId ungranted_scan
=
380 AddGallery("uscan", MediaGalleryPrefInfo::kScanResult
, 1, 0, 0);
381 MediaGalleryPrefId granted_scan
=
382 AddGallery("gscan", MediaGalleryPrefInfo::kScanResult
, 0, 2, 0);
383 gallery_prefs()->SetGalleryPermissionForExtension(*extension(), granted_scan
,
385 EXPECT_EQ(galleries_before
+ 2, gallery_prefs()->known_galleries().size());
387 // Run once with no scan results. "uscan" should go away, but "gscan" should
389 MediaFolderFinder::MediaFolderFinderResults found_folders
;
390 SetFindFoldersResults(true, found_folders
);
392 MediaGalleryScanResult file_counts
;
393 SetExpectedScanResults(0 /*gallery_count*/, file_counts
);
396 base::RunLoop().RunUntilIdle();
397 EXPECT_EQ(1, FindFolderDestroyCount());
398 EXPECT_EQ(galleries_before
+ 1, gallery_prefs()->known_galleries().size());
399 CheckFileCounts(granted_scan
, 0, 2, 0);
401 MediaGalleryPrefId id
=
402 AddGallery("uscan", MediaGalleryPrefInfo::kScanResult
, 1, 1, 1);
403 EXPECT_NE(id
, ungranted_scan
);
406 // Add scan results near the existing scan results.
407 file_counts
.audio_count
= 0;
408 file_counts
.image_count
= 0;
409 file_counts
.video_count
= 7;
410 base::FilePath path
= MakeTestFolder("uscan");
411 found_folders
[path
] = file_counts
;
413 file_counts
.video_count
= 11;
414 path
= MakeTestFolder("gscan/dir1");
415 found_folders
[path
] = file_counts
;
417 SetFindFoldersResults(true, found_folders
);
418 file_counts
.video_count
= 7;
419 SetExpectedScanResults(1 /*gallery_count*/, file_counts
);
422 base::RunLoop().RunUntilIdle();
423 EXPECT_EQ(2, FindFolderDestroyCount());
424 EXPECT_EQ(galleries_before
+ 2, gallery_prefs()->known_galleries().size());
425 CheckFileCounts(granted_scan
, 0, 0, 11);
426 // The new scan result should be one more than it's previous id.
427 CheckFileCounts(ungranted_scan
+ 1, 0, 0, 7);
430 TEST_F(MediaScanManagerTest
, UpdateExistingCounts
) {
431 size_t galleries_before
= gallery_prefs()->known_galleries().size();
433 MediaGalleryPrefId auto_id
=
434 AddGallery("auto", MediaGalleryPrefInfo::kAutoDetected
, 1, 0, 0);
435 MediaGalleryPrefId user_id
=
436 AddGallery("user", MediaGalleryPrefInfo::kUserAdded
, 0, 2, 0);
437 MediaGalleryPrefId scan_id
=
438 AddGallery("scan", MediaGalleryPrefInfo::kScanResult
, 0, 0, 3);
439 // Grant permission so this one isn't removed and readded.
440 gallery_prefs()->SetGalleryPermissionForExtension(*extension(), scan_id
,
442 CheckFileCounts(auto_id
, 1, 0, 0);
443 CheckFileCounts(user_id
, 0, 2, 0);
444 CheckFileCounts(scan_id
, 0, 0, 3);
446 MediaFolderFinder::MediaFolderFinderResults found_folders
;
447 MediaGalleryScanResult file_counts
;
448 file_counts
.audio_count
= 4;
449 base::FilePath path
= MakeTestFolder("auto/dir1");
450 found_folders
[path
] = file_counts
;
452 file_counts
.audio_count
= 5;
453 path
= MakeTestFolder("user/dir2");
454 found_folders
[path
] = file_counts
;
456 file_counts
.audio_count
= 6;
457 path
= MakeTestFolder("scan");
458 found_folders
[path
] = file_counts
;
460 SetFindFoldersResults(true, found_folders
);
462 file_counts
.audio_count
= 0;
463 SetExpectedScanResults(0 /*gallery_count*/, file_counts
);
466 base::RunLoop().RunUntilIdle();
467 EXPECT_EQ(1, FindFolderDestroyCount());
468 EXPECT_EQ(galleries_before
+ 3, gallery_prefs()->known_galleries().size());
469 CheckFileCounts(auto_id
, 4, 0, 0);
470 CheckFileCounts(user_id
, 5, 0, 0);
471 CheckFileCounts(scan_id
, 6, 0, 0);