Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / media_galleries / gallery_watch_manager_unittest.cc
blob5a944693db7a5abce0e4685a3a66555893837fb4
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/bind.h"
6 #include "base/command_line.h"
7 #include "base/files/file_path.h"
8 #include "base/files/file_util.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/run_loop.h"
12 #include "base/test/scoped_path_override.h"
13 #include "chrome/browser/extensions/test_extension_system.h"
14 #include "chrome/browser/media_galleries/gallery_watch_manager.h"
15 #include "chrome/browser/media_galleries/gallery_watch_manager_observer.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/test/base/testing_profile.h"
20 #include "components/storage_monitor/test_storage_monitor.h"
21 #include "content/public/test/test_browser_thread_bundle.h"
22 #include "extensions/browser/extension_system.h"
23 #include "extensions/common/extension.h"
24 #include "extensions/common/permissions/media_galleries_permission.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 #if defined(OS_CHROMEOS)
28 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
29 #include "chrome/browser/chromeos/settings/cros_settings.h"
30 #include "chrome/browser/chromeos/settings/device_settings_service.h"
31 #endif
33 namespace component_updater {
35 namespace {
37 void ConfirmWatch(base::RunLoop* loop, const std::string& error) {
38 EXPECT_TRUE(error.empty());
39 loop->Quit();
42 void ExpectWatchError(base::RunLoop* loop,
43 const std::string& expected_error,
44 const std::string& error) {
45 EXPECT_EQ(expected_error, error);
46 loop->Quit();
49 } // namespace
51 class GalleryWatchManagerTest : public GalleryWatchManagerObserver,
52 public testing::Test {
53 public:
54 GalleryWatchManagerTest()
55 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
56 profile_(new TestingProfile()),
57 gallery_prefs_(NULL),
58 expect_gallery_changed_(false),
59 expect_gallery_watch_dropped_(false),
60 pending_loop_(NULL) {}
62 ~GalleryWatchManagerTest() override {}
64 void SetUp() override {
65 monitor_ = storage_monitor::TestStorageMonitor::CreateAndInstall();
66 ASSERT_TRUE(monitor_);
68 extensions::TestExtensionSystem* extension_system(
69 static_cast<extensions::TestExtensionSystem*>(
70 extensions::ExtensionSystem::Get(profile_.get())));
71 extension_system->CreateExtensionService(
72 base::CommandLine::ForCurrentProcess(), base::FilePath(), false);
74 gallery_prefs_ =
75 MediaGalleriesPreferencesFactory::GetForProfile(profile_.get());
76 base::RunLoop loop;
77 gallery_prefs_->EnsureInitialized(loop.QuitClosure());
78 loop.Run();
80 std::vector<std::string> read_permissions;
81 read_permissions.push_back(
82 extensions::MediaGalleriesPermission::kReadPermission);
83 extension_ = AddMediaGalleriesApp("read", read_permissions, profile_.get());
85 manager_.reset(new GalleryWatchManager);
86 manager_->AddObserver(profile_.get(), this);
89 void TearDown() override {
90 if (profile_) {
91 manager_->RemoveObserver(profile_.get());
93 manager_.reset();
94 storage_monitor::TestStorageMonitor::Destroy();
97 protected:
98 // Create the specified path, and add it to preferences as a gallery.
99 MediaGalleryPrefId AddGallery(const base::FilePath& path) {
100 MediaGalleryPrefInfo gallery_info;
101 EXPECT_FALSE(gallery_prefs_->LookUpGalleryByPath(path, &gallery_info));
102 MediaGalleryPrefId id =
103 gallery_prefs_->AddGallery(gallery_info.device_id,
104 gallery_info.path,
105 MediaGalleryPrefInfo::kUserAdded,
106 gallery_info.volume_label,
107 gallery_info.vendor_name,
108 gallery_info.model_name,
109 gallery_info.total_size_in_bytes,
110 gallery_info.last_attach_time,
114 EXPECT_NE(kInvalidMediaGalleryPrefId, id);
116 EXPECT_TRUE(gallery_prefs_->SetGalleryPermissionForExtension(
117 *extension_, id, true));
118 return id;
121 TestingProfile* profile() { return profile_.get(); }
123 GalleryWatchManager* manager() { return manager_.get(); }
125 extensions::Extension* extension() { return extension_.get(); }
127 MediaGalleriesPreferences* gallery_prefs() { return gallery_prefs_; }
129 storage_monitor::TestStorageMonitor* storage_monitor() { return monitor_; }
131 bool GalleryWatchesSupported() {
132 return base::FilePathWatcher::RecursiveWatchAvailable();
135 void AddAndConfirmWatch(MediaGalleryPrefId gallery_id) {
136 base::RunLoop loop;
137 manager()->AddWatch(profile(),
138 extension(),
139 gallery_id,
140 base::Bind(&ConfirmWatch, base::Unretained(&loop)));
141 loop.Run();
144 void ExpectGalleryChanged(base::RunLoop* loop) {
145 expect_gallery_changed_ = true;
146 pending_loop_ = loop;
149 void ExpectGalleryWatchDropped(base::RunLoop* loop) {
150 expect_gallery_watch_dropped_ = true;
151 pending_loop_ = loop;
154 void ShutdownProfile() { profile_.reset(nullptr); }
156 private:
157 // GalleryWatchManagerObserver implementation.
158 void OnGalleryChanged(const std::string& extension_id,
159 MediaGalleryPrefId gallery_id) override {
160 EXPECT_TRUE(expect_gallery_changed_);
161 pending_loop_->Quit();
164 void OnGalleryWatchDropped(const std::string& extension_id,
165 MediaGalleryPrefId gallery_id) override {
166 EXPECT_TRUE(expect_gallery_watch_dropped_);
167 pending_loop_->Quit();
170 scoped_ptr<GalleryWatchManager> manager_;
172 // Needed for extension service & friends to work.
173 content::TestBrowserThreadBundle thread_bundle_;
175 scoped_refptr<extensions::Extension> extension_;
177 EnsureMediaDirectoriesExists mock_gallery_locations_;
179 #if defined(OS_CHROMEOS)
180 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
181 chromeos::ScopedTestCrosSettings test_cros_settings_;
182 chromeos::ScopedTestUserManager test_user_manager_;
183 #endif
185 storage_monitor::TestStorageMonitor* monitor_;
186 scoped_ptr<TestingProfile> profile_;
187 MediaGalleriesPreferences* gallery_prefs_;
189 bool expect_gallery_changed_;
190 bool expect_gallery_watch_dropped_;
191 base::RunLoop* pending_loop_;
193 DISALLOW_COPY_AND_ASSIGN(GalleryWatchManagerTest);
196 TEST_F(GalleryWatchManagerTest, Basic) {
197 base::ScopedTempDir temp_dir;
198 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
199 MediaGalleryPrefId id = AddGallery(temp_dir.path());
201 base::RunLoop loop;
202 if (GalleryWatchesSupported()) {
203 manager()->AddWatch(profile(),
204 extension(),
206 base::Bind(&ConfirmWatch, base::Unretained(&loop)));
207 } else {
208 manager()->AddWatch(
209 profile(),
210 extension(),
212 base::Bind(&ExpectWatchError,
213 base::Unretained(&loop),
214 GalleryWatchManager::kCouldNotWatchGalleryError));
216 loop.Run();
219 TEST_F(GalleryWatchManagerTest, AddAndRemoveTwoWatches) {
220 if (!GalleryWatchesSupported())
221 return;
223 EXPECT_TRUE(manager()->GetWatchSet(profile(), extension()->id()).empty());
225 base::ScopedTempDir temp1;
226 ASSERT_TRUE(temp1.CreateUniqueTempDir());
227 MediaGalleryPrefId id1 = AddGallery(temp1.path());
229 base::ScopedTempDir temp2;
230 ASSERT_TRUE(temp2.CreateUniqueTempDir());
231 MediaGalleryPrefId id2 = AddGallery(temp2.path());
233 // Add first watch and test it was added correctly.
234 AddAndConfirmWatch(id1);
235 MediaGalleryPrefIdSet set1 =
236 manager()->GetWatchSet(profile(), extension()->id());
237 EXPECT_EQ(1u, set1.size());
238 EXPECT_TRUE(ContainsKey(set1, id1));
240 // Test that the second watch was added correctly too.
241 AddAndConfirmWatch(id2);
242 MediaGalleryPrefIdSet set2 =
243 manager()->GetWatchSet(profile(), extension()->id());
244 EXPECT_EQ(2u, set2.size());
245 EXPECT_TRUE(ContainsKey(set2, id1));
246 EXPECT_TRUE(ContainsKey(set2, id2));
248 // Remove first watch and test that the second is still in there.
249 manager()->RemoveWatch(profile(), extension()->id(), id1);
250 MediaGalleryPrefIdSet set3 =
251 manager()->GetWatchSet(profile(), extension()->id());
252 EXPECT_EQ(1u, set3.size());
253 EXPECT_TRUE(ContainsKey(set3, id2));
255 // Try removing the first watch again and test that it has no effect.
256 manager()->RemoveWatch(profile(), extension()->id(), id1);
257 EXPECT_EQ(1u, manager()->GetWatchSet(profile(), extension()->id()).size());
259 // Remove the second watch and test that the new watch set is empty.
260 manager()->RemoveWatch(profile(), extension()->id(), id2);
261 EXPECT_TRUE(manager()->GetWatchSet(profile(), extension()->id()).empty());
264 TEST_F(GalleryWatchManagerTest, RemoveAllWatches) {
265 if (!GalleryWatchesSupported())
266 return;
268 base::ScopedTempDir temp1;
269 ASSERT_TRUE(temp1.CreateUniqueTempDir());
270 MediaGalleryPrefId id1 = AddGallery(temp1.path());
272 base::ScopedTempDir temp2;
273 ASSERT_TRUE(temp2.CreateUniqueTempDir());
274 MediaGalleryPrefId id2 = AddGallery(temp2.path());
276 // Add watches.
277 AddAndConfirmWatch(id1);
278 AddAndConfirmWatch(id2);
280 EXPECT_EQ(2u, manager()->GetWatchSet(profile(), extension()->id()).size());
282 // RemoveAllWatches using a different extension ID and verify watches remain.
283 manager()->RemoveAllWatches(profile(), "OtherExtensionId");
284 EXPECT_EQ(2u, manager()->GetWatchSet(profile(), extension()->id()).size());
286 // RemoveAllWatches using the correct extension ID and verify watches gone.
288 manager()->RemoveAllWatches(profile(), extension()->id());
289 EXPECT_TRUE(manager()->GetWatchSet(profile(), extension()->id()).empty());
292 TEST_F(GalleryWatchManagerTest, DropWatchOnGalleryRemoved) {
293 if (!GalleryWatchesSupported())
294 return;
296 base::ScopedTempDir temp_dir;
297 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
298 MediaGalleryPrefId id = AddGallery(temp_dir.path());
299 AddAndConfirmWatch(id);
301 base::RunLoop success_loop;
302 ExpectGalleryWatchDropped(&success_loop);
303 gallery_prefs()->EraseGalleryById(id);
304 success_loop.Run();
307 TEST_F(GalleryWatchManagerTest, DropWatchOnGalleryPermissionRevoked) {
308 if (!GalleryWatchesSupported())
309 return;
311 base::ScopedTempDir temp_dir;
312 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
313 MediaGalleryPrefId id = AddGallery(temp_dir.path());
314 AddAndConfirmWatch(id);
316 base::RunLoop success_loop;
317 ExpectGalleryWatchDropped(&success_loop);
318 gallery_prefs()->SetGalleryPermissionForExtension(*extension(), id, false);
319 success_loop.Run();
322 TEST_F(GalleryWatchManagerTest, DropWatchOnStorageRemoved) {
323 if (!GalleryWatchesSupported())
324 return;
326 // Create a temporary directory and treat is as a removable storage device.
327 base::ScopedTempDir temp_dir;
328 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
329 storage_monitor()->AddRemovablePath(temp_dir.path());
330 storage_monitor::StorageInfo storage_info;
331 ASSERT_TRUE(
332 storage_monitor()->GetStorageInfoForPath(temp_dir.path(), &storage_info));
333 storage_monitor()->receiver()->ProcessAttach(storage_info);
335 MediaGalleryPrefId id = AddGallery(temp_dir.path());
336 AddAndConfirmWatch(id);
338 base::RunLoop success_loop;
339 ExpectGalleryWatchDropped(&success_loop);
340 storage_monitor()->receiver()->ProcessDetach(storage_info.device_id());
341 success_loop.Run();
344 TEST_F(GalleryWatchManagerTest, TestWatchOperation) {
345 if (!GalleryWatchesSupported())
346 return;
348 base::ScopedTempDir temp_dir;
349 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
350 MediaGalleryPrefId id = AddGallery(temp_dir.path());
351 AddAndConfirmWatch(id);
353 base::RunLoop success_loop;
354 ExpectGalleryChanged(&success_loop);
355 ASSERT_EQ(
356 4, base::WriteFile(temp_dir.path().AppendASCII("fake file"), "blah", 4));
357 success_loop.Run();
360 TEST_F(GalleryWatchManagerTest, TestWatchOperationAfterProfileShutdown) {
361 if (!GalleryWatchesSupported())
362 return;
364 base::ScopedTempDir temp_dir;
365 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
366 MediaGalleryPrefId id = AddGallery(temp_dir.path());
367 AddAndConfirmWatch(id);
369 ShutdownProfile();
371 // Trigger a watch that should have been removed when the profile was
372 // destroyed to catch regressions. crbug.com/467627
373 base::RunLoop run_loop;
374 ASSERT_EQ(
375 4, base::WriteFile(temp_dir.path().AppendASCII("fake file"), "blah", 4));
376 run_loop.RunUntilIdle();
379 TEST_F(GalleryWatchManagerTest, TestStorageRemovedAfterProfileShutdown) {
380 if (!GalleryWatchesSupported())
381 return;
383 // Create a temporary directory and treat is as a removable storage device.
384 base::ScopedTempDir temp_dir;
385 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
386 storage_monitor()->AddRemovablePath(temp_dir.path());
387 storage_monitor::StorageInfo storage_info;
388 ASSERT_TRUE(
389 storage_monitor()->GetStorageInfoForPath(temp_dir.path(), &storage_info));
390 storage_monitor()->receiver()->ProcessAttach(storage_info);
392 MediaGalleryPrefId id = AddGallery(temp_dir.path());
393 AddAndConfirmWatch(id);
395 ShutdownProfile();
397 // Trigger a removable storage event that should be ignored now that the
398 // profile has been destroyed to catch regressions. crbug.com/467627
399 base::RunLoop run_loop;
400 storage_monitor()->receiver()->ProcessDetach(storage_info.device_id());
401 run_loop.RunUntilIdle();
404 } // namespace component_updater