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. 4 5 #include "base/auto_reset.h" 6 #include "base/file_util.h" 7 #include "base/files/scoped_temp_dir.h" 8 #include "base/json/json_writer.h" 9 #include "base/path_service.h" 10 #include "base/safe_numerics.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "base/values.h" 13 #include "chrome/browser/apps/app_browsertest_util.h" 14 #include "chrome/browser/browser_process.h" 15 #include "chrome/browser/extensions/extension_system.h" 16 #include "chrome/browser/media_galleries/media_file_system_registry.h" 17 #include "chrome/browser/media_galleries/media_galleries_preferences.h" 18 #include "chrome/browser/media_galleries/media_galleries_test_util.h" 19 #include "chrome/browser/storage_monitor/storage_info.h" 20 #include "chrome/browser/storage_monitor/storage_monitor.h" 21 #include "chrome/common/chrome_paths.h" 22 #include "content/public/test/test_utils.h" 23 24 #if defined(OS_WIN) || defined(OS_MACOSX) 25 #include "chrome/browser/media_galleries/fileapi/picasa_finder.h" 26 #include "chrome/common/media_galleries/picasa_test_util.h" 27 #include "chrome/common/media_galleries/picasa_types.h" 28 #include "chrome/common/media_galleries/pmp_test_util.h" 29 #endif 30 31 using extensions::PlatformAppBrowserTest; 32 33 namespace { 34 35 // Dummy device properties. 36 const char kDeviceId[] = "testDeviceId"; 37 const char kDeviceName[] = "foobar"; 38 #if defined(FILE_PATH_USES_DRIVE_LETTERS) 39 base::FilePath::CharType kDevicePath[] = FILE_PATH_LITERAL("C:\\qux"); 40 #else 41 base::FilePath::CharType kDevicePath[] = FILE_PATH_LITERAL("/qux"); 42 #endif 43 44 } // namespace 45 46 class MediaGalleriesPlatformAppBrowserTest : public PlatformAppBrowserTest { 47 protected: 48 MediaGalleriesPlatformAppBrowserTest() : test_jpg_size_(0) {} 49 virtual ~MediaGalleriesPlatformAppBrowserTest() {} 50 51 virtual void SetUpOnMainThread() OVERRIDE { 52 PlatformAppBrowserTest::SetUpOnMainThread(); 53 ensure_media_directories_exists_.reset(new EnsureMediaDirectoriesExists); 54 55 int64 file_size; 56 ASSERT_TRUE(base::GetFileSize(GetCommonDataDir().AppendASCII("test.jpg"), 57 &file_size)); 58 test_jpg_size_ = base::checked_numeric_cast<int>(file_size); 59 } 60 61 virtual void TearDownOnMainThread() OVERRIDE { 62 ensure_media_directories_exists_.reset(); 63 PlatformAppBrowserTest::TearDownOnMainThread(); 64 } 65 66 bool RunMediaGalleriesTest(const std::string& extension_name) { 67 base::ListValue empty_list_value; 68 return RunMediaGalleriesTestWithArg(extension_name, empty_list_value); 69 } 70 71 bool RunMediaGalleriesTestWithArg(const std::string& extension_name, 72 const base::ListValue& custom_arg_value) { 73 // Copy the test data for this test into a temporary directory. Then add 74 // a common_injected.js to the temporary copy and run it. 75 const char kTestDir[] = "api_test/media_galleries/"; 76 base::FilePath from_dir = 77 test_data_dir_.AppendASCII(kTestDir + extension_name); 78 from_dir = from_dir.NormalizePathSeparators(); 79 80 base::ScopedTempDir temp_dir; 81 if (!temp_dir.CreateUniqueTempDir()) 82 return false; 83 84 if (!base::CopyDirectory(from_dir, temp_dir.path(), true)) 85 return false; 86 87 base::FilePath common_js_path( 88 GetCommonDataDir().AppendASCII("common_injected.js")); 89 base::FilePath inject_js_path( 90 temp_dir.path().AppendASCII(extension_name) 91 .AppendASCII("common_injected.js")); 92 if (!base::CopyFile(common_js_path, inject_js_path)) 93 return false; 94 95 const char* custom_arg = NULL; 96 std::string json_string; 97 if (!custom_arg_value.empty()) { 98 base::JSONWriter::Write(&custom_arg_value, &json_string); 99 custom_arg = json_string.c_str(); 100 } 101 102 base::AutoReset<base::FilePath> reset(&test_data_dir_, temp_dir.path()); 103 return RunPlatformAppTestWithArg(extension_name, custom_arg); 104 } 105 106 void AttachFakeDevice() { 107 device_id_ = StorageInfo::MakeDeviceId( 108 StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM, kDeviceId); 109 110 StorageMonitor::GetInstance()->receiver()->ProcessAttach( 111 StorageInfo(device_id_, base::string16(), kDevicePath, 112 ASCIIToUTF16(kDeviceName), base::string16(), 113 base::string16(), 0)); 114 content::RunAllPendingInMessageLoop(); 115 } 116 117 void DetachFakeDevice() { 118 StorageMonitor::GetInstance()->receiver()->ProcessDetach(device_id_); 119 content::RunAllPendingInMessageLoop(); 120 } 121 122 // Called if test only wants a single gallery it creates. 123 void RemoveAllGalleries() { 124 MediaGalleriesPreferences* preferences = GetAndInitializePreferences(); 125 126 // Make a copy, as the iterator would be invalidated otherwise. 127 const MediaGalleriesPrefInfoMap galleries = 128 preferences->known_galleries(); 129 for (MediaGalleriesPrefInfoMap::const_iterator it = galleries.begin(); 130 it != galleries.end(); ++it) { 131 preferences->ForgetGalleryById(it->first); 132 } 133 } 134 135 // This function makes a single fake gallery. This is needed to test platforms 136 // with no default media galleries, such as CHROMEOS. This fake gallery is 137 // pre-populated with a test.jpg and test.txt. 138 void MakeSingleFakeGallery() { 139 ASSERT_TRUE(fake_gallery_temp_dir_.CreateUniqueTempDir()); 140 141 MediaGalleriesPreferences* preferences = GetAndInitializePreferences(); 142 143 MediaGalleryPrefInfo gallery_info; 144 ASSERT_FALSE(preferences->LookUpGalleryByPath(fake_gallery_temp_dir_.path(), 145 &gallery_info)); 146 preferences->AddGallery(gallery_info.device_id, 147 gallery_info.path, 148 false /* user_added */, 149 gallery_info.volume_label, 150 gallery_info.vendor_name, 151 gallery_info.model_name, 152 gallery_info.total_size_in_bytes, 153 gallery_info.last_attach_time); 154 155 content::RunAllPendingInMessageLoop(); 156 157 base::FilePath test_data_path(GetCommonDataDir()); 158 base::FilePath write_path = fake_gallery_temp_dir_.path(); 159 160 // Valid file, should show up in JS as a FileEntry. 161 ASSERT_TRUE(base::CopyFile(test_data_path.AppendASCII("test.jpg"), 162 write_path.AppendASCII("test.jpg"))); 163 164 // Invalid file, should not show up as a FileEntry in JS at all. 165 ASSERT_TRUE(base::CopyFile(test_data_path.AppendASCII("test.txt"), 166 write_path.AppendASCII("test.txt"))); 167 } 168 169 #if defined(OS_WIN) || defined(OS_MACOSX) 170 void PopulatePicasaTestData(const base::FilePath& picasa_app_data_root) { 171 base::FilePath picasa_database_path = 172 picasa::MakePicasaDatabasePath(picasa_app_data_root); 173 base::FilePath picasa_temp_dir_path = 174 picasa_database_path.DirName().AppendASCII(picasa::kPicasaTempDirName); 175 ASSERT_TRUE(base::CreateDirectory(picasa_database_path)); 176 ASSERT_TRUE(base::CreateDirectory(picasa_temp_dir_path)); 177 178 // Create fake folder directories. 179 base::FilePath folders_root = 180 ensure_media_directories_exists_->GetFakePicasaFoldersRootPath(); 181 base::FilePath fake_folder_1 = folders_root.AppendASCII("folder1"); 182 base::FilePath fake_folder_2 = folders_root.AppendASCII("folder2"); 183 ASSERT_TRUE(base::CreateDirectory(fake_folder_1)); 184 ASSERT_TRUE(base::CreateDirectory(fake_folder_2)); 185 186 // Write folder and album contents. 187 picasa::WriteTestAlbumTable( 188 picasa_database_path, fake_folder_1, fake_folder_2); 189 picasa::WriteTestAlbumsImagesIndex(fake_folder_1, fake_folder_2); 190 191 base::FilePath test_jpg_path = GetCommonDataDir().AppendASCII("test.jpg"); 192 ASSERT_TRUE(base::CopyFile( 193 test_jpg_path, fake_folder_1.AppendASCII("InBoth.jpg"))); 194 ASSERT_TRUE(base::CopyFile( 195 test_jpg_path, fake_folder_1.AppendASCII("InSecondAlbumOnly.jpg"))); 196 ASSERT_TRUE(base::CopyFile( 197 test_jpg_path, fake_folder_2.AppendASCII("InFirstAlbumOnly.jpg"))); 198 } 199 #endif 200 201 base::FilePath GetCommonDataDir() const { 202 return test_data_dir_.AppendASCII("api_test") 203 .AppendASCII("media_galleries") 204 .AppendASCII("common"); 205 } 206 207 int num_galleries() const { 208 return ensure_media_directories_exists_->num_galleries(); 209 } 210 211 int test_jpg_size() const { return test_jpg_size_; } 212 213 EnsureMediaDirectoriesExists* ensure_media_directories_exists() const { 214 return ensure_media_directories_exists_.get(); 215 } 216 217 private: 218 MediaGalleriesPreferences* GetAndInitializePreferences() { 219 MediaGalleriesPreferences* preferences = 220 g_browser_process->media_file_system_registry()->GetPreferences( 221 browser()->profile()); 222 base::RunLoop runloop; 223 preferences->EnsureInitialized(runloop.QuitClosure()); 224 runloop.Run(); 225 return preferences; 226 } 227 228 std::string device_id_; 229 base::ScopedTempDir fake_gallery_temp_dir_; 230 int test_jpg_size_; 231 scoped_ptr<EnsureMediaDirectoriesExists> ensure_media_directories_exists_; 232 }; 233 234 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, 235 MediaGalleriesNoAccess) { 236 MakeSingleFakeGallery(); 237 238 base::ListValue custom_args; 239 custom_args.AppendInteger(num_galleries() + 1); 240 241 ASSERT_TRUE(RunMediaGalleriesTestWithArg("no_access", custom_args)) 242 << message_; 243 } 244 245 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, NoGalleriesRead) { 246 ASSERT_TRUE(RunMediaGalleriesTest("no_galleries")) << message_; 247 } 248 249 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, 250 NoGalleriesCopyTo) { 251 ASSERT_TRUE(RunMediaGalleriesTest("no_galleries_copy_to")) << message_; 252 } 253 254 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, 255 MediaGalleriesRead) { 256 RemoveAllGalleries(); 257 MakeSingleFakeGallery(); 258 base::ListValue custom_args; 259 custom_args.AppendInteger(test_jpg_size()); 260 261 ASSERT_TRUE(RunMediaGalleriesTestWithArg("read_access", custom_args)) 262 << message_; 263 } 264 265 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, 266 MediaGalleriesCopyTo) { 267 RemoveAllGalleries(); 268 MakeSingleFakeGallery(); 269 ASSERT_TRUE(RunMediaGalleriesTest("copy_to_access")) << message_; 270 } 271 272 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, 273 MediaGalleriesDelete) { 274 MakeSingleFakeGallery(); 275 base::ListValue custom_args; 276 custom_args.AppendInteger(num_galleries() + 1); 277 ASSERT_TRUE(RunMediaGalleriesTestWithArg("delete_access", custom_args)) 278 << message_; 279 } 280 281 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, 282 MediaGalleriesAccessAttached) { 283 AttachFakeDevice(); 284 285 base::ListValue custom_args; 286 custom_args.AppendInteger(num_galleries() + 1); 287 custom_args.AppendString(kDeviceName); 288 289 ASSERT_TRUE(RunMediaGalleriesTestWithArg("access_attached", custom_args)) 290 << message_; 291 292 DetachFakeDevice(); 293 } 294 295 #if defined(OS_WIN)|| defined(OS_MACOSX) 296 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, 297 PicasaDefaultLocation) { 298 #if defined(OS_WIN) 299 PopulatePicasaTestData( 300 ensure_media_directories_exists()->GetFakeLocalAppDataPath()); 301 #elif defined(OS_MACOSX) 302 PopulatePicasaTestData( 303 ensure_media_directories_exists()->GetFakeAppDataPath()); 304 #endif 305 306 base::ListValue custom_args; 307 custom_args.AppendInteger(test_jpg_size()); 308 ASSERT_TRUE(RunMediaGalleriesTestWithArg("picasa", custom_args)) << message_; 309 } 310 311 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, 312 PicasaCustomLocation) { 313 base::ScopedTempDir custom_picasa_app_data_root; 314 ASSERT_TRUE(custom_picasa_app_data_root.CreateUniqueTempDir()); 315 ensure_media_directories_exists()->SetCustomPicasaAppDataPath( 316 custom_picasa_app_data_root.path()); 317 PopulatePicasaTestData(custom_picasa_app_data_root.path()); 318 319 base::ListValue custom_args; 320 custom_args.AppendInteger(test_jpg_size()); 321 ASSERT_TRUE(RunMediaGalleriesTestWithArg("picasa", custom_args)) << message_; 322 } 323 #endif // defined(OS_WIN) || defined(OS_MACOSX) 324