Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / media_galleries / media_file_system_registry_unittest.cc
blobcebd0a0f0f9a9c52276f2b74643dd04e931e0981
1 // Copyright (c) 2012 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 // MediaFileSystemRegistry unit tests.
7 #include <algorithm>
8 #include <set>
10 #include "base/bind_helpers.h"
11 #include "base/command_line.h"
12 #include "base/files/file_util.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/memory/scoped_vector.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/path_service.h"
19 #include "base/run_loop.h"
20 #include "base/stl_util.h"
21 #include "base/strings/stringprintf.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "base/threading/sequenced_worker_pool.h"
24 #include "base/values.h"
25 #include "chrome/browser/extensions/extension_service.h"
26 #include "chrome/browser/extensions/test_extension_system.h"
27 #include "chrome/browser/media_galleries/media_file_system_context.h"
28 #include "chrome/browser/media_galleries/media_file_system_registry.h"
29 #include "chrome/browser/media_galleries/media_galleries_preferences_factory.h"
30 #include "chrome/browser/media_galleries/media_galleries_test_util.h"
31 #include "chrome/common/chrome_paths.h"
32 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
33 #include "chrome/test/base/testing_browser_process.h"
34 #include "chrome/test/base/testing_profile.h"
35 #include "components/storage_monitor/removable_device_constants.h"
36 #include "components/storage_monitor/storage_info.h"
37 #include "components/storage_monitor/storage_monitor.h"
38 #include "components/storage_monitor/test_storage_monitor.h"
39 #include "content/public/browser/render_process_host.h"
40 #include "content/public/browser/render_process_host_factory.h"
41 #include "content/public/browser/web_contents.h"
42 #include "content/public/test/mock_render_process_host.h"
43 #include "content/public/test/test_browser_thread.h"
44 #include "content/public/test/web_contents_tester.h"
45 #include "extensions/browser/extension_system.h"
46 #include "extensions/common/extension.h"
47 #include "sync/api/string_ordinal.h"
48 #include "testing/gtest/include/gtest/gtest.h"
50 #if defined(OS_CHROMEOS)
51 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
52 #include "chrome/browser/chromeos/settings/cros_settings.h"
53 #include "chrome/browser/chromeos/settings/device_settings_service.h"
54 #endif
56 using content::BrowserThread;
57 using storage_monitor::StorageInfo;
58 using storage_monitor::StorageMonitor;
59 using storage_monitor::TestStorageMonitor;
61 // Not anonymous so it can be friends with MediaFileSystemRegistry.
62 class TestMediaFileSystemContext : public MediaFileSystemContext {
63 public:
64 struct FSInfo {
65 FSInfo() {}
66 FSInfo(const std::string& device_id, const base::FilePath& path,
67 const std::string& fs_name);
69 bool operator<(const FSInfo& other) const;
71 std::string device_id;
72 base::FilePath path;
73 std::string fs_name;
76 explicit TestMediaFileSystemContext(MediaFileSystemRegistry* registry);
77 ~TestMediaFileSystemContext() override {}
79 // MediaFileSystemContext implementation.
80 bool RegisterFileSystem(const std::string& device_id,
81 const std::string& fs_name,
82 const base::FilePath& path) override;
84 void RevokeFileSystem(const std::string& fs_name) override;
86 base::FilePath GetRegisteredPath(const std::string& fs_name) const override;
88 MediaFileSystemRegistry* registry() { return registry_; }
90 private:
91 void AddFSEntry(const std::string& device_id,
92 const base::FilePath& path,
93 const std::string& fs_name);
95 MediaFileSystemRegistry* registry_;
97 // The currently allocated mock file systems.
98 std::map<std::string /*fs_name*/, FSInfo> file_systems_by_name_;
101 TestMediaFileSystemContext::FSInfo::FSInfo(const std::string& device_id,
102 const base::FilePath& path,
103 const std::string& fs_name)
104 : device_id(device_id),
105 path(path),
106 fs_name(fs_name) {
109 bool TestMediaFileSystemContext::FSInfo::operator<(const FSInfo& other) const {
110 if (device_id != other.device_id)
111 return device_id < other.device_id;
112 if (path.value() != other.path.value())
113 return path.value() < other.path.value();
114 return fs_name < other.fs_name;
117 TestMediaFileSystemContext::TestMediaFileSystemContext(
118 MediaFileSystemRegistry* registry)
119 : registry_(registry) {
120 registry_->file_system_context_.reset(this);
123 bool TestMediaFileSystemContext::RegisterFileSystem(
124 const std::string& device_id,
125 const std::string& fs_name,
126 const base::FilePath& path) {
127 AddFSEntry(device_id, path, fs_name);
128 return true;
131 void TestMediaFileSystemContext::RevokeFileSystem(const std::string& fs_name) {
132 if (!ContainsKey(file_systems_by_name_, fs_name))
133 return;
134 EXPECT_EQ(1U, file_systems_by_name_.erase(fs_name));
137 base::FilePath TestMediaFileSystemContext::GetRegisteredPath(
138 const std::string& fs_name) const {
139 std::map<std::string /*fs_name*/, FSInfo>::const_iterator it =
140 file_systems_by_name_.find(fs_name);
141 if (it == file_systems_by_name_.end())
142 return base::FilePath();
143 return it->second.path;
146 void TestMediaFileSystemContext::AddFSEntry(const std::string& device_id,
147 const base::FilePath& path,
148 const std::string& fs_name) {
149 DCHECK_CURRENTLY_ON(BrowserThread::UI);
150 DCHECK(path.IsAbsolute());
151 DCHECK(!path.ReferencesParent());
153 FSInfo info(device_id, path, fs_name);
154 file_systems_by_name_[fs_name] = info;
157 namespace {
159 typedef std::map<MediaGalleryPrefId, MediaFileSystemInfo> FSInfoMap;
161 void GetGalleryInfoCallback(
162 FSInfoMap* results,
163 const std::vector<MediaFileSystemInfo>& file_systems) {
164 for (size_t i = 0; i < file_systems.size(); ++i) {
165 ASSERT_FALSE(ContainsKey(*results, file_systems[i].pref_id));
166 (*results)[file_systems[i].pref_id] = file_systems[i];
170 void CheckGalleryInfo(const MediaFileSystemInfo& info,
171 TestMediaFileSystemContext* fs_context,
172 const base::FilePath& path,
173 bool removable,
174 bool media_device) {
175 EXPECT_EQ(path, info.path);
176 EXPECT_EQ(removable, info.removable);
177 EXPECT_EQ(media_device, info.media_device);
178 EXPECT_NE(0UL, info.pref_id);
180 if (removable)
181 EXPECT_NE(0UL, info.transient_device_id.size());
182 else
183 EXPECT_EQ(0UL, info.transient_device_id.size());
185 base::FilePath fsid_path = fs_context->GetRegisteredPath(info.fsid);
186 EXPECT_EQ(path, fsid_path);
189 class MockProfileSharedRenderProcessHostFactory
190 : public content::RenderProcessHostFactory {
191 public:
192 MockProfileSharedRenderProcessHostFactory() {}
193 ~MockProfileSharedRenderProcessHostFactory() override;
195 // RPH created with this factory are owned by it. If the RPH is destroyed
196 // for testing purposes, it must be removed from the factory first.
197 content::MockRenderProcessHost* ReleaseRPH(
198 content::BrowserContext* browser_context);
200 content::RenderProcessHost* CreateRenderProcessHost(
201 content::BrowserContext* browser_context,
202 content::SiteInstance* site_instance) const override;
204 private:
205 typedef std::map<content::BrowserContext*, content::MockRenderProcessHost*>
206 ProfileRPHMap;
207 mutable ProfileRPHMap rph_map_;
209 DISALLOW_COPY_AND_ASSIGN(MockProfileSharedRenderProcessHostFactory);
212 class ProfileState {
213 public:
214 explicit ProfileState(
215 MockProfileSharedRenderProcessHostFactory* rph_factory);
216 ~ProfileState();
218 MediaGalleriesPreferences* GetMediaGalleriesPrefs();
220 void CheckGalleries(
221 const std::string& test,
222 const std::vector<MediaFileSystemInfo>& regular_extension_galleries,
223 const std::vector<MediaFileSystemInfo>& all_extension_galleries);
225 FSInfoMap GetGalleriesInfo(extensions::Extension* extension);
227 extensions::Extension* all_permission_extension();
228 extensions::Extension* regular_permission_extension();
229 Profile* profile();
231 void AddNameForReadCompare(const base::string16& name);
232 void AddNameForAllCompare(const base::string16& name);
234 private:
235 void CompareResults(const std::string& test,
236 const std::vector<base::string16>& names,
237 const std::vector<MediaFileSystemInfo>& expected,
238 const std::vector<MediaFileSystemInfo>& actual);
239 bool ContainsEntry(const MediaFileSystemInfo& info,
240 const std::vector<MediaFileSystemInfo>& container);
242 int GetAndClearComparisonCount();
244 int num_comparisons_;
246 scoped_ptr<TestingProfile> profile_;
248 scoped_refptr<extensions::Extension> all_permission_extension_;
249 scoped_refptr<extensions::Extension> regular_permission_extension_;
250 scoped_refptr<extensions::Extension> no_permissions_extension_;
252 scoped_ptr<content::WebContents> single_web_contents_;
253 scoped_ptr<content::WebContents> shared_web_contents1_;
254 scoped_ptr<content::WebContents> shared_web_contents2_;
256 // The RenderProcessHosts are freed when their respective WebContents /
257 // RenderViewHosts go away.
258 content::MockRenderProcessHost* single_rph_;
259 content::MockRenderProcessHost* shared_rph_;
261 std::vector<base::string16> compare_names_read_;
262 std::vector<base::string16> compare_names_all_;
264 DISALLOW_COPY_AND_ASSIGN(ProfileState);
267 base::string16 GetExpectedFolderName(const base::FilePath& path) {
268 #if defined(OS_CHROMEOS)
269 return path.BaseName().LossyDisplayName();
270 #else
271 return path.LossyDisplayName();
272 #endif
275 } // namespace
277 class MediaFileSystemRegistryTest : public ChromeRenderViewHostTestHarness {
278 public:
279 void CreateProfileState(size_t profile_count);
281 ProfileState* GetProfileState(size_t i);
283 MediaGalleriesPreferences* GetPreferences(Profile* profile);
285 base::FilePath empty_dir() {
286 return empty_dir_;
289 base::FilePath dcim_dir() {
290 return dcim_dir_;
293 TestMediaFileSystemContext* test_file_system_context() {
294 return test_file_system_context_;
297 // Create a user added gallery based on the information passed and add it to
298 // |profiles|. Returns the device id.
299 std::string AddUserGallery(StorageInfo::Type type,
300 const std::string& unique_id,
301 const base::FilePath& path);
303 // Returns the device id.
304 std::string AttachDevice(StorageInfo::Type type,
305 const std::string& unique_id,
306 const base::FilePath& location);
308 void DetachDevice(const std::string& device_id);
310 void SetGalleryPermission(ProfileState* profile_state,
311 extensions::Extension* extension,
312 const std::string& device_id,
313 bool has_access);
315 void AssertAllAutoAddedGalleries();
317 void InitForGalleriesInfoTest(FSInfoMap* galleries_info);
319 void CheckNewGalleryInfo(ProfileState* profile_state,
320 const FSInfoMap& galleries_info,
321 const base::FilePath& location,
322 bool removable,
323 bool media_device);
325 std::vector<MediaFileSystemInfo> GetAutoAddedGalleries(
326 ProfileState* profile_state);
328 void ProcessAttach(const std::string& id,
329 const base::string16& name,
330 const base::FilePath::StringType& location) {
331 StorageInfo info(id, location, name, base::string16(), base::string16(), 0);
332 StorageMonitor::GetInstance()->receiver()->ProcessAttach(info);
335 void ProcessDetach(const std::string& id) {
336 StorageMonitor::GetInstance()->receiver()->ProcessDetach(id);
339 MediaFileSystemRegistry* registry() {
340 return test_file_system_context_->registry();
343 size_t GetExtensionGalleriesHostCount(
344 const MediaFileSystemRegistry* registry) const;
346 int num_auto_galleries() {
347 return media_directories_.num_galleries();
350 protected:
351 void SetUp() override;
352 void TearDown() override;
354 private:
355 // This makes sure that at least one default gallery exists on the file
356 // system.
357 EnsureMediaDirectoriesExists media_directories_;
359 // Some test gallery directories.
360 base::ScopedTempDir galleries_dir_;
361 // An empty directory in |galleries_dir_|
362 base::FilePath empty_dir_;
363 // A directory in |galleries_dir_| with a DCIM directory in it.
364 base::FilePath dcim_dir_;
366 // MediaFileSystemRegistry owns this.
367 TestMediaFileSystemContext* test_file_system_context_;
369 // Needed for extension service & friends to work.
371 #if defined(OS_CHROMEOS)
372 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
373 chromeos::ScopedTestCrosSettings test_cros_settings_;
374 scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_;
375 #endif
377 MockProfileSharedRenderProcessHostFactory rph_factory_;
379 ScopedVector<ProfileState> profile_states_;
382 namespace {
384 bool MediaFileSystemInfoComparator(const MediaFileSystemInfo& a,
385 const MediaFileSystemInfo& b) {
386 CHECK_NE(a.name, b.name); // Name must be unique.
387 return a.name < b.name;
390 ///////////////////////////////////////////////
391 // MockProfileSharedRenderProcessHostFactory //
392 ///////////////////////////////////////////////
394 MockProfileSharedRenderProcessHostFactory::
395 ~MockProfileSharedRenderProcessHostFactory() {
396 STLDeleteValues(&rph_map_);
399 content::MockRenderProcessHost*
400 MockProfileSharedRenderProcessHostFactory::ReleaseRPH(
401 content::BrowserContext* browser_context) {
402 ProfileRPHMap::iterator existing = rph_map_.find(browser_context);
403 if (existing == rph_map_.end())
404 return NULL;
405 content::MockRenderProcessHost* result = existing->second;
406 rph_map_.erase(existing);
407 return result;
410 content::RenderProcessHost*
411 MockProfileSharedRenderProcessHostFactory::CreateRenderProcessHost(
412 content::BrowserContext* browser_context,
413 content::SiteInstance* site_instance) const {
414 ProfileRPHMap::const_iterator existing = rph_map_.find(browser_context);
415 if (existing != rph_map_.end())
416 return existing->second;
417 rph_map_[browser_context] =
418 new content::MockRenderProcessHost(browser_context);
419 return rph_map_[browser_context];
422 //////////////////
423 // ProfileState //
424 //////////////////
426 ProfileState::ProfileState(
427 MockProfileSharedRenderProcessHostFactory* rph_factory)
428 : num_comparisons_(0),
429 profile_(new TestingProfile()) {
430 extensions::TestExtensionSystem* extension_system(
431 static_cast<extensions::TestExtensionSystem*>(
432 extensions::ExtensionSystem::Get(profile_.get())));
433 extension_system->CreateExtensionService(
434 base::CommandLine::ForCurrentProcess(), base::FilePath(), false);
436 std::vector<std::string> all_permissions;
437 all_permissions.push_back("allAutoDetected");
438 all_permissions.push_back("read");
439 std::vector<std::string> read_permissions;
440 read_permissions.push_back("read");
442 all_permission_extension_ =
443 AddMediaGalleriesApp("all", all_permissions, profile_.get());
444 regular_permission_extension_ =
445 AddMediaGalleriesApp("regular", read_permissions, profile_.get());
446 no_permissions_extension_ =
447 AddMediaGalleriesApp("no", read_permissions, profile_.get());
449 single_web_contents_.reset(
450 content::WebContentsTester::CreateTestWebContents(profile_.get(), NULL));
451 single_rph_ = rph_factory->ReleaseRPH(profile_.get());
453 shared_web_contents1_.reset(
454 content::WebContentsTester::CreateTestWebContents(profile_.get(), NULL));
455 shared_web_contents2_.reset(
456 content::WebContentsTester::CreateTestWebContents(profile_.get(), NULL));
457 shared_rph_ = rph_factory->ReleaseRPH(profile_.get());
460 ProfileState::~ProfileState() {
461 // TestExtensionSystem uses DeleteSoon, so we need to delete the profiles
462 // and then run the message queue to clean up. But first we have to
463 // delete everything that references the profile.
464 single_web_contents_.reset();
465 shared_web_contents1_.reset();
466 shared_web_contents2_.reset();
467 profile_.reset();
469 base::MessageLoop::current()->RunUntilIdle();
472 MediaGalleriesPreferences* ProfileState::GetMediaGalleriesPrefs() {
473 MediaGalleriesPreferences* prefs =
474 MediaGalleriesPreferencesFactory::GetForProfile(profile_.get());
475 base::RunLoop loop;
476 prefs->EnsureInitialized(loop.QuitClosure());
477 loop.Run();
478 return prefs;
481 void ProfileState::CheckGalleries(
482 const std::string& test,
483 const std::vector<MediaFileSystemInfo>& regular_extension_galleries,
484 const std::vector<MediaFileSystemInfo>& all_extension_galleries) {
485 MediaFileSystemRegistry* registry =
486 g_browser_process->media_file_system_registry();
488 // No Media Galleries permissions.
489 std::vector<MediaFileSystemInfo> empty_expectation;
490 std::vector<base::string16> empty_names;
491 registry->GetMediaFileSystemsForExtension(
492 single_web_contents_.get(), no_permissions_extension_.get(),
493 base::Bind(&ProfileState::CompareResults, base::Unretained(this),
494 base::StringPrintf("%s (no permission)", test.c_str()),
495 base::ConstRef(empty_names),
496 base::ConstRef(empty_expectation)));
497 base::MessageLoop::current()->RunUntilIdle();
498 EXPECT_EQ(1, GetAndClearComparisonCount());
500 // Read permission only.
501 registry->GetMediaFileSystemsForExtension(
502 single_web_contents_.get(), regular_permission_extension_.get(),
503 base::Bind(&ProfileState::CompareResults, base::Unretained(this),
504 base::StringPrintf("%s (regular permission)", test.c_str()),
505 base::ConstRef(compare_names_read_),
506 base::ConstRef(regular_extension_galleries)));
507 base::MessageLoop::current()->RunUntilIdle();
508 EXPECT_EQ(1, GetAndClearComparisonCount());
510 // All galleries permission.
511 registry->GetMediaFileSystemsForExtension(
512 single_web_contents_.get(), all_permission_extension_.get(),
513 base::Bind(&ProfileState::CompareResults, base::Unretained(this),
514 base::StringPrintf("%s (all permission)", test.c_str()),
515 base::ConstRef(compare_names_all_),
516 base::ConstRef(all_extension_galleries)));
517 base::MessageLoop::current()->RunUntilIdle();
518 EXPECT_EQ(1, GetAndClearComparisonCount());
521 FSInfoMap ProfileState::GetGalleriesInfo(extensions::Extension* extension) {
522 FSInfoMap results;
523 MediaFileSystemRegistry* registry =
524 g_browser_process->media_file_system_registry();
525 registry->GetMediaFileSystemsForExtension(
526 single_web_contents_.get(), extension,
527 base::Bind(&GetGalleryInfoCallback, base::Unretained(&results)));
528 base::MessageLoop::current()->RunUntilIdle();
529 return results;
532 extensions::Extension* ProfileState::all_permission_extension() {
533 return all_permission_extension_.get();
536 extensions::Extension* ProfileState::regular_permission_extension() {
537 return regular_permission_extension_.get();
540 Profile* ProfileState::profile() {
541 return profile_.get();
544 void ProfileState::AddNameForReadCompare(const base::string16& name) {
545 compare_names_read_.push_back(name);
548 void ProfileState::AddNameForAllCompare(const base::string16& name) {
549 compare_names_all_.push_back(name);
552 bool ProfileState::ContainsEntry(
553 const MediaFileSystemInfo& info,
554 const std::vector<MediaFileSystemInfo>& container) {
555 for (size_t i = 0; i < container.size(); ++i) {
556 if (info.path.value() == container[i].path.value()) {
557 EXPECT_FALSE(container[i].fsid.empty());
558 if (!info.fsid.empty())
559 EXPECT_EQ(info.fsid, container[i].fsid);
560 return true;
563 return false;
566 void ProfileState::CompareResults(
567 const std::string& test,
568 const std::vector<base::string16>& names,
569 const std::vector<MediaFileSystemInfo>& expected,
570 const std::vector<MediaFileSystemInfo>& actual) {
571 num_comparisons_++;
572 EXPECT_EQ(expected.size(), actual.size()) << test;
574 // Order isn't important, so sort the results.
575 std::vector<MediaFileSystemInfo> sorted(actual);
576 std::sort(sorted.begin(), sorted.end(), MediaFileSystemInfoComparator);
577 std::vector<MediaFileSystemInfo> expect(expected);
578 std::sort(expect.begin(), expect.end(), MediaFileSystemInfoComparator);
579 std::vector<base::string16> expect_names(names);
580 std::sort(expect_names.begin(), expect_names.end());
582 for (size_t i = 0; i < expect.size() && i < sorted.size(); ++i) {
583 if (expect_names.size() > i)
584 EXPECT_EQ(expect_names[i], sorted[i].name) << test;
585 EXPECT_TRUE(ContainsEntry(expect[i], sorted)) << test;
589 int ProfileState::GetAndClearComparisonCount() {
590 int result = num_comparisons_;
591 num_comparisons_ = 0;
592 return result;
595 } // namespace
597 /////////////////////////////////
598 // MediaFileSystemRegistryTest //
599 /////////////////////////////////
601 void MediaFileSystemRegistryTest::CreateProfileState(size_t profile_count) {
602 for (size_t i = 0; i < profile_count; ++i) {
603 ProfileState* state = new ProfileState(&rph_factory_);
604 profile_states_.push_back(state);
608 ProfileState* MediaFileSystemRegistryTest::GetProfileState(size_t i) {
609 return profile_states_[i];
612 MediaGalleriesPreferences* MediaFileSystemRegistryTest::GetPreferences(
613 Profile* profile) {
614 MediaGalleriesPreferences* prefs = registry()->GetPreferences(profile);
615 base::RunLoop loop;
616 prefs->EnsureInitialized(loop.QuitClosure());
617 loop.Run();
618 return prefs;
621 std::string MediaFileSystemRegistryTest::AddUserGallery(
622 StorageInfo::Type type,
623 const std::string& unique_id,
624 const base::FilePath& path) {
625 std::string device_id = StorageInfo::MakeDeviceId(type, unique_id);
626 DCHECK(!StorageInfo::IsMediaDevice(device_id));
628 for (size_t i = 0; i < profile_states_.size(); ++i) {
629 profile_states_[i]->GetMediaGalleriesPrefs()->AddGallery(
630 device_id, base::FilePath(), MediaGalleryPrefInfo::kUserAdded,
631 base::string16(), base::string16(), base::string16(), 0,
632 base::Time::Now(), 0, 0, 0);
634 return device_id;
637 std::string MediaFileSystemRegistryTest::AttachDevice(
638 StorageInfo::Type type,
639 const std::string& unique_id,
640 const base::FilePath& location) {
641 std::string device_id = StorageInfo::MakeDeviceId(type, unique_id);
642 DCHECK(StorageInfo::IsRemovableDevice(device_id));
643 base::string16 label = location.BaseName().LossyDisplayName();
644 ProcessAttach(device_id, label, location.value());
645 base::MessageLoop::current()->RunUntilIdle();
646 return device_id;
649 void MediaFileSystemRegistryTest::DetachDevice(const std::string& device_id) {
650 DCHECK(StorageInfo::IsRemovableDevice(device_id));
651 ProcessDetach(device_id);
652 base::MessageLoop::current()->RunUntilIdle();
655 void MediaFileSystemRegistryTest::SetGalleryPermission(
656 ProfileState* profile_state, extensions::Extension* extension,
657 const std::string& device_id, bool has_access) {
658 MediaGalleriesPreferences* preferences =
659 profile_state->GetMediaGalleriesPrefs();
660 MediaGalleryPrefIdSet pref_id =
661 preferences->LookUpGalleriesByDeviceId(device_id);
662 ASSERT_EQ(1U, pref_id.size());
663 preferences->SetGalleryPermissionForExtension(*extension, *pref_id.begin(),
664 has_access);
667 void MediaFileSystemRegistryTest::AssertAllAutoAddedGalleries() {
668 for (size_t i = 0; i < profile_states_.size(); ++i) {
669 MediaGalleriesPreferences* prefs =
670 profile_states_[0]->GetMediaGalleriesPrefs();
672 // Make sure that we have at least one gallery and that they are all
673 // auto added galleries.
674 const MediaGalleriesPrefInfoMap& galleries = prefs->known_galleries();
675 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
676 ASSERT_GT(galleries.size(), 0U);
677 #endif
678 for (MediaGalleriesPrefInfoMap::const_iterator it = galleries.begin();
679 it != galleries.end();
680 ++it) {
681 ASSERT_EQ(MediaGalleryPrefInfo::kAutoDetected, it->second.type);
686 void MediaFileSystemRegistryTest::InitForGalleriesInfoTest(
687 FSInfoMap* galleries_info) {
688 CreateProfileState(1);
689 AssertAllAutoAddedGalleries();
691 // Get all existing gallery names.
692 ProfileState* profile_state = GetProfileState(0U);
693 *galleries_info = profile_state->GetGalleriesInfo(
694 profile_state->all_permission_extension());
695 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
696 ASSERT_EQ(3U, galleries_info->size());
697 #else
698 ASSERT_EQ(0U, galleries_info->size());
699 #endif
702 void MediaFileSystemRegistryTest::CheckNewGalleryInfo(
703 ProfileState* profile_state,
704 const FSInfoMap& galleries_info,
705 const base::FilePath& location,
706 bool removable,
707 bool media_device) {
708 // Get new galleries.
709 FSInfoMap new_galleries_info = profile_state->GetGalleriesInfo(
710 profile_state->all_permission_extension());
711 ASSERT_EQ(galleries_info.size() + 1U, new_galleries_info.size());
713 bool found_new = false;
714 for (FSInfoMap::const_iterator it = new_galleries_info.begin();
715 it != new_galleries_info.end();
716 ++it) {
717 if (ContainsKey(galleries_info, it->first))
718 continue;
720 ASSERT_FALSE(found_new);
721 CheckGalleryInfo(it->second, test_file_system_context_, location,
722 removable, media_device);
723 found_new = true;
725 ASSERT_TRUE(found_new);
728 std::vector<MediaFileSystemInfo>
729 MediaFileSystemRegistryTest::GetAutoAddedGalleries(
730 ProfileState* profile_state) {
731 const MediaGalleriesPrefInfoMap& galleries =
732 profile_state->GetMediaGalleriesPrefs()->known_galleries();
733 std::vector<MediaFileSystemInfo> result;
734 for (MediaGalleriesPrefInfoMap::const_iterator it = galleries.begin();
735 it != galleries.end();
736 ++it) {
737 if (it->second.type == MediaGalleryPrefInfo::kAutoDetected) {
738 base::FilePath path = it->second.AbsolutePath();
739 MediaFileSystemInfo info(path.BaseName().LossyDisplayName(), path,
740 std::string(), 0, std::string(), false, false);
741 result.push_back(info);
744 std::sort(result.begin(), result.end(), MediaFileSystemInfoComparator);
745 return result;
748 size_t MediaFileSystemRegistryTest::GetExtensionGalleriesHostCount(
749 const MediaFileSystemRegistry* registry) const {
750 size_t extension_galleries_host_count = 0;
751 for (MediaFileSystemRegistry::ExtensionGalleriesHostMap::const_iterator it =
752 registry->extension_hosts_map_.begin();
753 it != registry->extension_hosts_map_.end();
754 ++it) {
755 extension_galleries_host_count += it->second.size();
757 return extension_galleries_host_count;
761 void MediaFileSystemRegistryTest::SetUp() {
762 ChromeRenderViewHostTestHarness::SetUp();
763 ASSERT_TRUE(TestStorageMonitor::CreateAndInstall());
765 DeleteContents();
766 SetRenderProcessHostFactory(&rph_factory_);
768 test_file_system_context_ = new TestMediaFileSystemContext(
769 g_browser_process->media_file_system_registry());
771 #if defined(OS_CHROMEOS)
772 test_user_manager_.reset(new chromeos::ScopedTestUserManager());
773 #endif
775 ASSERT_TRUE(galleries_dir_.CreateUniqueTempDir());
776 empty_dir_ = galleries_dir_.path().AppendASCII("empty");
777 ASSERT_TRUE(base::CreateDirectory(empty_dir_));
778 dcim_dir_ = galleries_dir_.path().AppendASCII("with_dcim");
779 ASSERT_TRUE(base::CreateDirectory(dcim_dir_));
780 ASSERT_TRUE(base::CreateDirectory(
781 dcim_dir_.Append(storage_monitor::kDCIMDirectoryName)));
784 void MediaFileSystemRegistryTest::TearDown() {
785 profile_states_.clear();
786 MediaFileSystemRegistry* registry =
787 g_browser_process->media_file_system_registry();
788 EXPECT_EQ(0U, GetExtensionGalleriesHostCount(registry));
789 TestStorageMonitor::Destroy();
790 #if defined(OS_CHROMEOS)
791 test_user_manager_.reset();
792 #endif
794 ChromeRenderViewHostTestHarness::TearDown();
797 ///////////
798 // Tests //
799 ///////////
801 TEST_F(MediaFileSystemRegistryTest, Basic) {
802 CreateProfileState(1);
803 AssertAllAutoAddedGalleries();
805 ProfileState* profile_state = GetProfileState(0);
806 std::vector<MediaFileSystemInfo> auto_galleries =
807 GetAutoAddedGalleries(profile_state);
808 std::vector<MediaFileSystemInfo> empty_expectation;
809 profile_state->CheckGalleries("basic", empty_expectation, auto_galleries);
812 TEST_F(MediaFileSystemRegistryTest, UserAddedGallery) {
813 CreateProfileState(1);
814 AssertAllAutoAddedGalleries();
815 ProfileState* profile_state = GetProfileState(0);
816 std::vector<MediaFileSystemInfo> auto_galleries =
817 GetAutoAddedGalleries(profile_state);
818 std::vector<MediaFileSystemInfo> added_galleries;
819 profile_state->CheckGalleries("user added init", added_galleries,
820 auto_galleries);
822 // Add a user gallery to the regular permission extension.
823 std::string device_id = AddUserGallery(StorageInfo::FIXED_MASS_STORAGE,
824 empty_dir().AsUTF8Unsafe(),
825 empty_dir());
826 SetGalleryPermission(profile_state,
827 profile_state->regular_permission_extension(),
828 device_id,
829 true /*has access*/);
830 MediaFileSystemInfo added_info(empty_dir().LossyDisplayName(), empty_dir(),
831 std::string(), 0, std::string(), false, false);
832 added_galleries.push_back(added_info);
833 profile_state->CheckGalleries("user added regular", added_galleries,
834 auto_galleries);
836 // Add it to the all galleries extension.
837 SetGalleryPermission(profile_state,
838 profile_state->all_permission_extension(),
839 device_id,
840 true /*has access*/);
841 auto_galleries.push_back(added_info);
842 profile_state->CheckGalleries("user added all", added_galleries,
843 auto_galleries);
846 // Regression test to make sure erasing galleries does not result a crash.
847 TEST_F(MediaFileSystemRegistryTest, EraseGalleries) {
848 CreateProfileState(1);
849 AssertAllAutoAddedGalleries();
851 ProfileState* profile_state = GetProfileState(0);
852 std::vector<MediaFileSystemInfo> auto_galleries =
853 GetAutoAddedGalleries(profile_state);
854 std::vector<MediaFileSystemInfo> empty_expectation;
855 profile_state->CheckGalleries("erase", empty_expectation, auto_galleries);
857 MediaGalleriesPreferences* prefs = profile_state->GetMediaGalleriesPrefs();
858 MediaGalleriesPrefInfoMap galleries = prefs->known_galleries();
859 for (MediaGalleriesPrefInfoMap::const_iterator it = galleries.begin();
860 it != galleries.end(); ++it) {
861 prefs->ForgetGalleryById(it->first);
865 // Regression test to make sure calling GetPreferences() does not re-insert
866 // galleries on auto-detected removable devices that were blacklisted.
867 TEST_F(MediaFileSystemRegistryTest,
868 GetPreferencesDoesNotReinsertBlacklistedGalleries) {
869 CreateProfileState(1);
870 AssertAllAutoAddedGalleries();
872 ProfileState* profile_state = GetProfileState(0);
873 const size_t gallery_count = GetAutoAddedGalleries(profile_state).size();
875 // Attach a device.
876 const std::string device_id = AttachDevice(
877 StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM,
878 "removable_dcim_fake_id",
879 dcim_dir());
880 EXPECT_EQ(gallery_count + 1, GetAutoAddedGalleries(profile_state).size());
882 // Forget the device.
883 bool forget_gallery = false;
884 MediaGalleriesPreferences* prefs = GetPreferences(profile_state->profile());
885 const MediaGalleriesPrefInfoMap& galleries = prefs->known_galleries();
886 for (MediaGalleriesPrefInfoMap::const_iterator it = galleries.begin();
887 it != galleries.end(); ++it) {
888 if (it->second.device_id == device_id) {
889 prefs->ForgetGalleryById(it->first);
890 forget_gallery = true;
891 break;
894 base::MessageLoop::current()->RunUntilIdle();
895 EXPECT_TRUE(forget_gallery);
896 EXPECT_EQ(gallery_count, GetAutoAddedGalleries(profile_state).size());
898 // Call GetPreferences() and the gallery count should not change.
899 prefs = GetPreferences(profile_state->profile());
900 EXPECT_EQ(gallery_count, GetAutoAddedGalleries(profile_state).size());
903 TEST_F(MediaFileSystemRegistryTest, GalleryNameDefault) {
904 FSInfoMap galleries_info;
905 InitForGalleriesInfoTest(&galleries_info);
907 for (FSInfoMap::const_iterator it = galleries_info.begin();
908 it != galleries_info.end();
909 ++it) {
910 CheckGalleryInfo(it->second, test_file_system_context(),
911 it->second.path, false, false);
915 // TODO(gbillock): Move the remaining test into the linux directory.
916 #if !defined(OS_MACOSX) && !defined(OS_WIN)
917 TEST_F(MediaFileSystemRegistryTest, GalleryMTP) {
918 FSInfoMap galleries_info;
919 InitForGalleriesInfoTest(&galleries_info);
921 base::FilePath location(FILE_PATH_LITERAL("/mtp_bogus"));
922 AttachDevice(StorageInfo::MTP_OR_PTP, "mtp_fake_id", location);
923 CheckNewGalleryInfo(GetProfileState(0U), galleries_info, location,
924 true /*removable*/, true /* media device */);
926 #endif
928 TEST_F(MediaFileSystemRegistryTest, GalleryDCIM) {
929 FSInfoMap galleries_info;
930 InitForGalleriesInfoTest(&galleries_info);
932 AttachDevice(StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM,
933 "removable_dcim_fake_id",
934 dcim_dir());
935 CheckNewGalleryInfo(GetProfileState(0U), galleries_info, dcim_dir(),
936 true /*removable*/, true /* media device */);
939 TEST_F(MediaFileSystemRegistryTest, GalleryNoDCIM) {
940 FSInfoMap galleries_info;
941 InitForGalleriesInfoTest(&galleries_info);
943 std::string device_id =
944 AttachDevice(StorageInfo::REMOVABLE_MASS_STORAGE_NO_DCIM,
945 empty_dir().AsUTF8Unsafe(),
946 empty_dir());
947 std::string device_id2 =
948 AddUserGallery(StorageInfo::REMOVABLE_MASS_STORAGE_NO_DCIM,
949 empty_dir().AsUTF8Unsafe(),
950 empty_dir());
951 ASSERT_EQ(device_id, device_id2);
952 // Add permission for new non-default gallery.
953 ProfileState* profile_state = GetProfileState(0U);
954 SetGalleryPermission(profile_state,
955 profile_state->all_permission_extension(),
956 device_id,
957 true /*has access*/);
958 CheckNewGalleryInfo(profile_state, galleries_info, empty_dir(),
959 true /*removable*/, false /* media device */);
962 TEST_F(MediaFileSystemRegistryTest, GalleryUserAddedPath) {
963 FSInfoMap galleries_info;
964 InitForGalleriesInfoTest(&galleries_info);
966 std::string device_id = AddUserGallery(StorageInfo::FIXED_MASS_STORAGE,
967 empty_dir().AsUTF8Unsafe(),
968 empty_dir());
969 // Add permission for new non-default gallery.
970 ProfileState* profile_state = GetProfileState(0U);
971 SetGalleryPermission(profile_state,
972 profile_state->all_permission_extension(),
973 device_id,
974 true /*has access*/);
975 CheckNewGalleryInfo(profile_state, galleries_info, empty_dir(),
976 false /*removable*/, false /* media device */);
979 TEST_F(MediaFileSystemRegistryTest, DetachedDeviceGalleryPath) {
980 const std::string device_id = AttachDevice(
981 StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM,
982 "removable_dcim_fake_id",
983 dcim_dir());
985 MediaGalleryPrefInfo pref_info;
986 pref_info.device_id = device_id;
987 EXPECT_EQ(dcim_dir().value(), pref_info.AbsolutePath().value());
989 MediaGalleryPrefInfo pref_info_with_relpath;
990 pref_info_with_relpath.path =
991 base::FilePath(FILE_PATH_LITERAL("test_relpath"));
992 pref_info_with_relpath.device_id = device_id;
993 EXPECT_EQ(dcim_dir().Append(pref_info_with_relpath.path).value(),
994 pref_info_with_relpath.AbsolutePath().value());
996 DetachDevice(device_id);
997 EXPECT_TRUE(pref_info.AbsolutePath().empty());
998 EXPECT_TRUE(pref_info_with_relpath.AbsolutePath().empty());
1001 TEST_F(MediaFileSystemRegistryTest, TestNameConstruction) {
1002 CreateProfileState(1);
1003 AssertAllAutoAddedGalleries();
1005 ProfileState* profile_state = GetProfileState(0);
1007 std::string user_gallery = AddUserGallery(StorageInfo::FIXED_MASS_STORAGE,
1008 empty_dir().AsUTF8Unsafe(),
1009 empty_dir());
1010 SetGalleryPermission(profile_state,
1011 profile_state->regular_permission_extension(),
1012 user_gallery,
1013 true /*has access*/);
1014 SetGalleryPermission(profile_state,
1015 profile_state->all_permission_extension(),
1016 user_gallery,
1017 true /*has access*/);
1019 std::vector<MediaFileSystemInfo> auto_galleries =
1020 GetAutoAddedGalleries(profile_state);
1021 MediaFileSystemInfo added_info(empty_dir().BaseName().LossyDisplayName(),
1022 empty_dir(), std::string(), 0, std::string(),
1023 false, false);
1024 auto_galleries.push_back(added_info);
1025 std::vector<MediaFileSystemInfo> one_expectation;
1026 one_expectation.push_back(added_info);
1028 base::string16 empty_dir_name = GetExpectedFolderName(empty_dir());
1029 profile_state->AddNameForReadCompare(empty_dir_name);
1030 profile_state->AddNameForAllCompare(empty_dir_name);
1032 // This part of the test is conditional on default directories existing
1033 // on the test platform. In ChromeOS, these directories do not exist.
1034 base::FilePath path;
1035 if (num_auto_galleries() > 0) {
1036 ASSERT_TRUE(PathService::Get(chrome::DIR_USER_MUSIC, &path));
1037 profile_state->AddNameForAllCompare(GetExpectedFolderName(path));
1038 ASSERT_TRUE(PathService::Get(chrome::DIR_USER_PICTURES, &path));
1039 profile_state->AddNameForAllCompare(GetExpectedFolderName(path));
1040 ASSERT_TRUE(PathService::Get(chrome::DIR_USER_VIDEOS, &path));
1041 profile_state->AddNameForAllCompare(GetExpectedFolderName(path));
1043 profile_state->CheckGalleries("names-dir", one_expectation, auto_galleries);
1044 } else {
1045 profile_state->CheckGalleries("names", one_expectation, one_expectation);
1049 TEST_F(MediaFileSystemRegistryTest, PreferenceListener) {
1050 CreateProfileState(1);
1051 AssertAllAutoAddedGalleries();
1053 // Add a user gallery to the regular permission extension.
1054 std::string device_id = AddUserGallery(StorageInfo::FIXED_MASS_STORAGE,
1055 empty_dir().AsUTF8Unsafe(),
1056 empty_dir());
1057 ProfileState* profile_state = GetProfileState(0);
1058 SetGalleryPermission(profile_state,
1059 profile_state->regular_permission_extension(),
1060 device_id,
1061 true /*has access*/);
1063 FSInfoMap fs_info = profile_state->GetGalleriesInfo(
1064 profile_state->regular_permission_extension());
1065 ASSERT_EQ(1U, fs_info.size());
1066 EXPECT_FALSE(test_file_system_context()->GetRegisteredPath(
1067 fs_info.begin()->second.fsid).empty());
1069 // Revoke permission and ensure that the file system is revoked.
1070 SetGalleryPermission(profile_state,
1071 profile_state->regular_permission_extension(),
1072 device_id,
1073 false /*has access*/);
1074 EXPECT_TRUE(test_file_system_context()->GetRegisteredPath(
1075 fs_info.begin()->second.fsid).empty());