Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / media_galleries / media_galleries_apitest.cc
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/numerics/safe_conversions.h"
10 #include "base/path_service.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "chrome/browser/apps/app_browsertest_util.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/media_galleries/media_file_system_registry.h"
17 #include "chrome/browser/media_galleries/media_folder_finder.h"
18 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
19 #include "chrome/browser/media_galleries/media_galleries_test_util.h"
20 #include "chrome/browser/media_galleries/media_scan_manager.h"
21 #include "chrome/common/chrome_paths.h"
22 #include "components/storage_monitor/storage_info.h"
23 #include "components/storage_monitor/storage_monitor.h"
24 #include "content/public/test/test_utils.h"
25 #include "extensions/browser/extension_system.h"
26
27 #if defined(OS_WIN) || defined(OS_MACOSX)
28 #include "chrome/browser/media_galleries/fileapi/picasa_finder.h"
29 #include "chrome/common/media_galleries/picasa_test_util.h"
30 #include "chrome/common/media_galleries/picasa_types.h"
31 #include "chrome/common/media_galleries/pmp_test_util.h"
32 #endif
33
34 #if defined(OS_MACOSX)
35 #include "base/mac/foundation_util.h"
36 #include "base/strings/sys_string_conversions.h"
37 #include "chrome/browser/media_galleries/fileapi/iapps_finder_impl.h"
38 #endif  // OS_MACOSX
39
40 using extensions::PlatformAppBrowserTest;
41
42 namespace {
43
44 // Dummy device properties.
45 const char kDeviceId[] = "testDeviceId";
46 const char kDeviceName[] = "foobar";
47 #if defined(FILE_PATH_USES_DRIVE_LETTERS)
48 base::FilePath::CharType kDevicePath[] = FILE_PATH_LITERAL("C:\\qux");
49 #else
50 base::FilePath::CharType kDevicePath[] = FILE_PATH_LITERAL("/qux");
51 #endif
52
53 void DoNothingMediaFolderFinderResultCallback(
54     bool /*success*/,
55     const MediaFolderFinder::MediaFolderFinderResults& /*results*/) {
56 }
57
58 class DoNothingMediaFolderFinder : public MediaFolderFinder {
59  public:
60   explicit DoNothingMediaFolderFinder(
61       const MediaFolderFinderResultsCallback& callback)
62       : MediaFolderFinder(callback) {
63   }
64   virtual ~DoNothingMediaFolderFinder() {}
65
66   static MediaFolderFinder* CreateDoNothingMediaFolderFinder(
67       const MediaFolderFinderResultsCallback& callback) {
68     return new DoNothingMediaFolderFinder(
69         base::Bind(&DoNothingMediaFolderFinderResultCallback));
70   }
71
72   virtual void StartScan() OVERRIDE {}
73
74  private:
75 };
76
77 }  // namespace
78
79 class MediaGalleriesPlatformAppBrowserTest : public PlatformAppBrowserTest {
80  protected:
81   MediaGalleriesPlatformAppBrowserTest() : test_jpg_size_(0) {}
82   virtual ~MediaGalleriesPlatformAppBrowserTest() {}
83
84   virtual void SetUpOnMainThread() OVERRIDE {
85     PlatformAppBrowserTest::SetUpOnMainThread();
86     ensure_media_directories_exists_.reset(new EnsureMediaDirectoriesExists);
87
88     int64 file_size;
89     ASSERT_TRUE(base::GetFileSize(GetCommonDataDir().AppendASCII("test.jpg"),
90                                   &file_size));
91     test_jpg_size_ = base::checked_cast<int>(file_size);
92   }
93
94   virtual void TearDownOnMainThread() OVERRIDE {
95     ensure_media_directories_exists_.reset();
96     PlatformAppBrowserTest::TearDownOnMainThread();
97   }
98
99   bool RunMediaGalleriesTest(const std::string& extension_name) {
100     base::ListValue empty_list_value;
101     return RunMediaGalleriesTestWithArg(extension_name, empty_list_value);
102   }
103
104   bool RunMediaGalleriesTestWithArg(const std::string& extension_name,
105                                     const base::ListValue& custom_arg_value) {
106     // Copy the test data for this test into a temporary directory. Then add
107     // a common_injected.js to the temporary copy and run it.
108     const char kTestDir[] = "api_test/media_galleries/";
109     base::FilePath from_dir =
110         test_data_dir_.AppendASCII(kTestDir + extension_name);
111     from_dir = from_dir.NormalizePathSeparators();
112
113     base::ScopedTempDir temp_dir;
114     if (!temp_dir.CreateUniqueTempDir())
115       return false;
116
117     if (!base::CopyDirectory(from_dir, temp_dir.path(), true))
118       return false;
119
120     base::FilePath common_js_path(
121         GetCommonDataDir().AppendASCII("common_injected.js"));
122     base::FilePath inject_js_path(
123         temp_dir.path().AppendASCII(extension_name)
124                        .AppendASCII("common_injected.js"));
125     if (!base::CopyFile(common_js_path, inject_js_path))
126       return false;
127
128     const char* custom_arg = NULL;
129     std::string json_string;
130     if (!custom_arg_value.empty()) {
131       base::JSONWriter::Write(&custom_arg_value, &json_string);
132       custom_arg = json_string.c_str();
133     }
134
135     base::AutoReset<base::FilePath> reset(&test_data_dir_, temp_dir.path());
136     bool result = RunPlatformAppTestWithArg(extension_name, custom_arg);
137     content::RunAllPendingInMessageLoop();  // avoid race on exit in registry.
138     return result;
139   }
140
141   void AttachFakeDevice() {
142     device_id_ = StorageInfo::MakeDeviceId(
143         StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM, kDeviceId);
144
145     StorageMonitor::GetInstance()->receiver()->ProcessAttach(
146         StorageInfo(device_id_, base::string16(), kDevicePath,
147                     base::ASCIIToUTF16(kDeviceName), base::string16(),
148                     base::string16(), 0));
149     content::RunAllPendingInMessageLoop();
150   }
151
152   void DetachFakeDevice() {
153     StorageMonitor::GetInstance()->receiver()->ProcessDetach(device_id_);
154     content::RunAllPendingInMessageLoop();
155   }
156
157   // Called if test only wants a single gallery it creates.
158   void RemoveAllGalleries() {
159     MediaGalleriesPreferences* preferences = GetAndInitializePreferences();
160
161     // Make a copy, as the iterator would be invalidated otherwise.
162     const MediaGalleriesPrefInfoMap galleries =
163         preferences->known_galleries();
164     for (MediaGalleriesPrefInfoMap::const_iterator it = galleries.begin();
165          it != galleries.end(); ++it) {
166       preferences->ForgetGalleryById(it->first);
167     }
168   }
169
170   // This function makes a single fake gallery. This is needed to test platforms
171   // with no default media galleries, such as CHROMEOS. This fake gallery is
172   // pre-populated with a test.jpg and test.txt.
173   void MakeSingleFakeGallery() {
174     ASSERT_TRUE(fake_gallery_temp_dir_.CreateUniqueTempDir());
175
176     MediaGalleriesPreferences* preferences = GetAndInitializePreferences();
177
178     MediaGalleryPrefInfo gallery_info;
179     ASSERT_FALSE(preferences->LookUpGalleryByPath(fake_gallery_temp_dir_.path(),
180                                                   &gallery_info));
181     preferences->AddGallery(gallery_info.device_id,
182                             gallery_info.path,
183                             MediaGalleryPrefInfo::kAutoDetected,
184                             gallery_info.volume_label,
185                             gallery_info.vendor_name,
186                             gallery_info.model_name,
187                             gallery_info.total_size_in_bytes,
188                             gallery_info.last_attach_time,
189                             0, 0, 0);
190
191     content::RunAllPendingInMessageLoop();
192
193     base::FilePath test_data_path(GetCommonDataDir());
194     base::FilePath write_path = fake_gallery_temp_dir_.path();
195
196     // Valid file, should show up in JS as a FileEntry.
197     ASSERT_TRUE(base::CopyFile(test_data_path.AppendASCII("test.jpg"),
198                                write_path.AppendASCII("test.jpg")));
199
200     // Invalid file, should not show up as a FileEntry in JS at all.
201     ASSERT_TRUE(base::CopyFile(test_data_path.AppendASCII("test.txt"),
202                                write_path.AppendASCII("test.txt")));
203   }
204
205 #if defined(OS_WIN) || defined(OS_MACOSX)
206   void PopulatePicasaTestData(const base::FilePath& picasa_app_data_root) {
207     base::FilePath picasa_database_path =
208         picasa::MakePicasaDatabasePath(picasa_app_data_root);
209     base::FilePath picasa_temp_dir_path =
210         picasa_database_path.DirName().AppendASCII(picasa::kPicasaTempDirName);
211     ASSERT_TRUE(base::CreateDirectory(picasa_database_path));
212     ASSERT_TRUE(base::CreateDirectory(picasa_temp_dir_path));
213
214     // Create fake folder directories.
215     base::FilePath folders_root =
216         ensure_media_directories_exists_->GetFakePicasaFoldersRootPath();
217     base::FilePath fake_folder_1 = folders_root.AppendASCII("folder1");
218     base::FilePath fake_folder_2 = folders_root.AppendASCII("folder2");
219     ASSERT_TRUE(base::CreateDirectory(fake_folder_1));
220     ASSERT_TRUE(base::CreateDirectory(fake_folder_2));
221
222     // Write folder and album contents.
223     picasa::WriteTestAlbumTable(
224         picasa_database_path, fake_folder_1, fake_folder_2);
225     picasa::WriteTestAlbumsImagesIndex(fake_folder_1, fake_folder_2);
226
227     base::FilePath test_jpg_path = GetCommonDataDir().AppendASCII("test.jpg");
228     ASSERT_TRUE(base::CopyFile(
229         test_jpg_path, fake_folder_1.AppendASCII("InBoth.jpg")));
230     ASSERT_TRUE(base::CopyFile(
231         test_jpg_path, fake_folder_1.AppendASCII("InSecondAlbumOnly.jpg")));
232     ASSERT_TRUE(base::CopyFile(
233         test_jpg_path, fake_folder_2.AppendASCII("InFirstAlbumOnly.jpg")));
234   }
235 #endif  // defined(OS_WIN) || defined(OS_MACOSX)
236
237 #if defined(OS_MACOSX)
238   void PopulateIPhotoTestData(const base::FilePath& iphoto_data_root) {
239     std::string xml_contents = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
240     "<plist version=\"1.0\">"
241     "<dict>\n"
242
243     "    <key>List of Albums</key>"
244     "    <array>\n"
245
246     "    <dict>\n"
247     "      <key>AlbumId</key>"
248     "      <integer>1</integer>"
249     "      <key>AlbumName</key>"
250     "      <string>Album1</string>"
251     "      <key>KeyList</key>\n"
252     "      <array>"
253     "      <string>1</string>"
254     "      <string>2</string>"
255     "      </array>\n"
256     "    </dict>\n"
257
258     "    <dict>\n"
259     "      <key>AlbumId</key>"
260     "      <integer>2</integer>"
261     "      <key>AlbumName</key>"
262     "      <string>Album2</string>"
263     "      <key>KeyList</key>\n"
264     "      <array>"
265     "      <string>2</string>"
266     "      </array>\n"
267     "    </dict>\n"
268
269     "    </array>\n"
270
271     "   <key>Master Image List</key>\n"
272     "   <dict>\n"
273
274     "  <key>1</key>"
275     "  <dict>\n"
276     "    <key>MediaType</key>"
277     "    <string>Image</string>"
278     "    <key>Caption</key>"
279     "    <string>caption 1</string>"
280     "    <key>GUID</key>"
281     "    <string>1</string>"
282     "    <key>ModDateAsTimerInterval</key>"
283     "    <string>386221543.0000</string>"
284     "    <key>DateAsTimerInterval</key>"
285     "    <string>386221543.0000</string>"
286     "    <key>DateAsTimerIntervalGMT</key>"
287     "    <string>385123456.00</string>"
288     "    <key>ImagePath</key>"
289     "    <string>$path1</string>"
290     "    <key>ThumbPath</key>"
291     "    <string>/thumb/path</string>\n"
292     "  </dict>\n"
293
294     "  <key>2</key>\n"
295     "  <dict>\n"
296     "    <key>MediaType</key>"
297     "    <string>Image</string>"
298     "    <key>Caption</key>"
299     "    <string>caption 2</string>"
300     "    <key>GUID</key>"
301     "    <string>2</string>"
302     "    <key>ModDateAsTimerInterval</key>"
303     "    <string>386221543.0000</string>"
304     "    <key>DateAsTimerInterval</key>"
305     "    <string>386221543.0000</string>"
306     "    <key>DateAsTimerIntervalGMT</key>"
307     "    <string>385123456.00</string>"
308     "    <key>ImagePath</key>"
309     "    <string>$path2</string>"
310     "    <key>ThumbPath</key>"
311     "    <string>/thumb/path2</string>\n"
312     "  </dict>\n"
313
314     "   </dict>\n"  // Master Image List
315
316     "</dict>\n"
317     "</plist>";
318
319     base::FilePath test_jpg_path = GetCommonDataDir().AppendASCII("test.jpg");
320     ASSERT_TRUE(base::CreateDirectory(iphoto_data_root));
321     base::FilePath first_only_jpg =
322         iphoto_data_root.AppendASCII("InFirstAlbumOnly.jpg");
323     base::FilePath in_both_jpg = iphoto_data_root.AppendASCII("InBoth.jpg");
324     ASSERT_TRUE(base::CopyFile(test_jpg_path, first_only_jpg));
325     ASSERT_TRUE(base::CopyFile(test_jpg_path, in_both_jpg));
326     ReplaceFirstSubstringAfterOffset(
327         &xml_contents, 0, std::string("$path1"), first_only_jpg.value());
328     ReplaceFirstSubstringAfterOffset(
329         &xml_contents, 0, std::string("$path2"), in_both_jpg.value());
330
331     base::FilePath album_xml = iphoto_data_root.AppendASCII("AlbumData.xml");
332     ASSERT_NE(-1, file_util::WriteFile(album_xml,
333                                        xml_contents.c_str(),
334                                        xml_contents.size()));
335   }
336 #endif  // defined(OS_MACOSX)
337
338   base::FilePath GetCommonDataDir() const {
339     return test_data_dir_.AppendASCII("api_test")
340                          .AppendASCII("media_galleries")
341                          .AppendASCII("common");
342   }
343
344   int num_galleries() const {
345     return ensure_media_directories_exists_->num_galleries();
346   }
347
348   int test_jpg_size() const { return test_jpg_size_; }
349
350   EnsureMediaDirectoriesExists* ensure_media_directories_exists() const {
351     return ensure_media_directories_exists_.get();
352   }
353
354   void InstallDoNothingFolderFinder() {
355     MediaScanManager * scan_manager =
356         g_browser_process->media_file_system_registry()->media_scan_manager();
357     scan_manager->SetMediaFolderFinderFactory(base::Bind(
358         &DoNothingMediaFolderFinder::CreateDoNothingMediaFolderFinder));
359   }
360
361  private:
362   MediaGalleriesPreferences* GetAndInitializePreferences() {
363     MediaGalleriesPreferences* preferences =
364         g_browser_process->media_file_system_registry()->GetPreferences(
365             browser()->profile());
366     base::RunLoop runloop;
367     preferences->EnsureInitialized(runloop.QuitClosure());
368     runloop.Run();
369     return preferences;
370   }
371
372   std::string device_id_;
373   base::ScopedTempDir fake_gallery_temp_dir_;
374   int test_jpg_size_;
375   scoped_ptr<EnsureMediaDirectoriesExists> ensure_media_directories_exists_;
376 };
377
378 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
379                        MediaGalleriesNoAccess) {
380   MakeSingleFakeGallery();
381
382   base::ListValue custom_args;
383   custom_args.AppendInteger(num_galleries() + 1);
384
385   ASSERT_TRUE(RunMediaGalleriesTestWithArg("no_access", custom_args))
386       << message_;
387 }
388
389 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, NoGalleriesRead) {
390   ASSERT_TRUE(RunMediaGalleriesTest("no_galleries")) << message_;
391 }
392
393 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
394                        NoGalleriesCopyTo) {
395   ASSERT_TRUE(RunMediaGalleriesTest("no_galleries_copy_to")) << message_;
396 }
397
398 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
399                        MediaGalleriesRead) {
400   RemoveAllGalleries();
401   MakeSingleFakeGallery();
402   base::ListValue custom_args;
403   custom_args.AppendInteger(test_jpg_size());
404
405   ASSERT_TRUE(RunMediaGalleriesTestWithArg("read_access", custom_args))
406       << message_;
407 }
408
409 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
410                        MediaGalleriesCopyTo) {
411   RemoveAllGalleries();
412   MakeSingleFakeGallery();
413   ASSERT_TRUE(RunMediaGalleriesTest("copy_to_access")) << message_;
414 }
415
416 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
417                        MediaGalleriesDelete) {
418   MakeSingleFakeGallery();
419   base::ListValue custom_args;
420   custom_args.AppendInteger(num_galleries() + 1);
421   ASSERT_TRUE(RunMediaGalleriesTestWithArg("delete_access", custom_args))
422       << message_;
423 }
424
425 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
426                        MediaGalleriesAccessAttached) {
427   AttachFakeDevice();
428
429   base::ListValue custom_args;
430   custom_args.AppendInteger(num_galleries() + 1);
431   custom_args.AppendString(kDeviceName);
432
433   ASSERT_TRUE(RunMediaGalleriesTestWithArg("access_attached", custom_args))
434       << message_;
435
436   DetachFakeDevice();
437 }
438
439 #if defined(OS_WIN)|| defined(OS_MACOSX)
440 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
441                        PicasaDefaultLocation) {
442 #if defined(OS_WIN)
443   PopulatePicasaTestData(
444       ensure_media_directories_exists()->GetFakeLocalAppDataPath());
445 #elif defined(OS_MACOSX)
446   PopulatePicasaTestData(
447       ensure_media_directories_exists()->GetFakeAppDataPath());
448 #endif
449
450   base::ListValue custom_args;
451   custom_args.AppendInteger(test_jpg_size());
452   ASSERT_TRUE(RunMediaGalleriesTestWithArg("picasa", custom_args)) << message_;
453 }
454
455 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
456                        PicasaCustomLocation) {
457   base::ScopedTempDir custom_picasa_app_data_root;
458   ASSERT_TRUE(custom_picasa_app_data_root.CreateUniqueTempDir());
459   ensure_media_directories_exists()->SetCustomPicasaAppDataPath(
460       custom_picasa_app_data_root.path());
461   PopulatePicasaTestData(custom_picasa_app_data_root.path());
462
463   base::ListValue custom_args;
464   custom_args.AppendInteger(test_jpg_size());
465   ASSERT_TRUE(RunMediaGalleriesTestWithArg("picasa", custom_args)) << message_;
466 }
467 #endif  // defined(OS_WIN) || defined(OS_MACOSX)
468
469 #if defined(OS_MACOSX)
470 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
471                        IPhotoTest) {
472   PopulateIPhotoTestData(
473       ensure_media_directories_exists()->GetFakeIPhotoRootPath());
474
475   base::ListValue custom_args;
476   custom_args.AppendInteger(test_jpg_size());
477   ASSERT_TRUE(RunMediaGalleriesTestWithArg("iphoto", custom_args)) << message_;
478
479   iapps::SetMacPreferencesForTesting(NULL);
480 }
481 #endif  // defined(OS_MACOSX)
482
483 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, Scan) {
484   InstallDoNothingFolderFinder();
485   ASSERT_TRUE(RunMediaGalleriesTest("scan")) << message_;
486 }