1 // Copyright 2013 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.
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/files/file_util.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/run_loop.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/synchronization/waitable_event.h"
17 #include "base/thread_task_runner_handle.h"
18 #include "base/time/time.h"
19 #include "chrome/browser/media_galleries/fileapi/iphoto_data_provider.h"
20 #include "chrome/browser/media_galleries/fileapi/iphoto_file_util.h"
21 #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
22 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
23 #include "chrome/browser/media_galleries/imported_media_gallery_registry.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/test/mock_special_storage_policy.h"
26 #include "content/public/test/test_browser_thread.h"
27 #include "content/public/test/test_file_system_options.h"
28 #include "storage/browser/fileapi/async_file_util.h"
29 #include "storage/browser/fileapi/external_mount_points.h"
30 #include "storage/browser/fileapi/file_system_context.h"
31 #include "storage/browser/fileapi/file_system_operation_context.h"
32 #include "storage/browser/fileapi/file_system_operation_runner.h"
33 #include "testing/gtest/include/gtest/gtest.h"
35 using storage::FileSystemOperationContext
;
36 using storage::FileSystemOperation
;
37 using storage::FileSystemURL
;
43 void ReadDirectoryTestHelperCallback(
44 base::RunLoop
* run_loop
,
45 FileSystemOperation::FileEntryList
* contents
,
47 base::File::Error error
,
48 const FileSystemOperation::FileEntryList
& file_list
,
51 *completed
= !has_more
&& error
== base::File::FILE_OK
;
52 *contents
= file_list
;
56 void ReadDirectoryTestHelper(storage::FileSystemOperationRunner
* runner
,
57 const FileSystemURL
& url
,
58 FileSystemOperation::FileEntryList
* contents
,
62 base::RunLoop run_loop
;
63 runner
->ReadDirectory(
64 url
, base::Bind(&ReadDirectoryTestHelperCallback
, &run_loop
, contents
,
71 class TestIPhotoDataProvider
: public IPhotoDataProvider
{
73 explicit TestIPhotoDataProvider(const base::FilePath
& fake_library_path
)
74 : IPhotoDataProvider(fake_library_path
) {
75 EXPECT_TRUE(fake_auto_add_dir_
.CreateUniqueTempDir());
78 ~TestIPhotoDataProvider() override
{}
80 void RefreshData(const ReadyCallback
& ready_callback
) override
{
81 ready_callback
.Run(true /* success */);
84 std::vector
<std::string
> GetAlbumNames() const override
{
85 std::vector
<std::string
> names
;
86 names
.push_back("Album1");
87 names
.push_back("has_originals");
91 std::map
<std::string
, base::FilePath
> GetAlbumContents(
92 const std::string
& album
) const override
{
93 std::map
<std::string
, base::FilePath
> contents
;
94 contents
["a.jpg"] = library_path().AppendASCII("a.jpg");
98 base::FilePath
GetPhotoLocationInAlbum(
99 const std::string
& album
,
100 const std::string
& filename
) const override
{
101 return library_path().AppendASCII("a.jpg");
104 bool HasOriginals(const std::string
& album
) const override
{
105 return (album
== "has_originals");
108 std::map
<std::string
, base::FilePath
> GetOriginals(
109 const std::string
& album
) const override
{
110 std::map
<std::string
, base::FilePath
> contents
;
111 contents
["a.jpg"] = library_path().AppendASCII("orig.jpg");
115 base::FilePath
GetOriginalPhotoLocation(
116 const std::string
& album
,
117 const std::string
& filename
) const override
{
118 return library_path().AppendASCII("orig.jpg");
122 base::ScopedTempDir fake_auto_add_dir_
;
125 class TestIPhotoFileUtil
: public IPhotoFileUtil
{
127 explicit TestIPhotoFileUtil(MediaPathFilter
* media_path_filter
,
128 IPhotoDataProvider
* data_provider
)
129 : IPhotoFileUtil(media_path_filter
),
130 data_provider_(data_provider
) {
132 ~TestIPhotoFileUtil() override
{}
135 IPhotoDataProvider
* GetDataProvider() override
{ return data_provider_
; }
137 IPhotoDataProvider
* data_provider_
;
140 class TestMediaFileSystemBackend
: public MediaFileSystemBackend
{
142 TestMediaFileSystemBackend(const base::FilePath
& profile_path
,
143 IPhotoFileUtil
* iphoto_file_util
)
144 : MediaFileSystemBackend(
146 MediaFileSystemBackend::MediaTaskRunner().get()),
147 test_file_util_(iphoto_file_util
) {}
149 storage::AsyncFileUtil
* GetAsyncFileUtil(
150 storage::FileSystemType type
) override
{
151 if (type
!= storage::kFileSystemTypeIphoto
)
154 return test_file_util_
.get();
158 scoped_ptr
<storage::AsyncFileUtil
> test_file_util_
;
161 class IPhotoFileUtilTest
: public testing::Test
{
164 : io_thread_(content::BrowserThread::IO
, &message_loop_
) {
167 void SetUpDataProvider() {
168 ASSERT_TRUE(fake_library_dir_
.CreateUniqueTempDir());
172 fake_library_dir_
.path().AppendASCII("a.jpg"),
178 fake_library_dir_
.path().AppendASCII("orig.jpg"),
182 iphoto_data_provider_
.reset(
183 new TestIPhotoDataProvider(fake_library_dir_
.path()));
186 void SetUp() override
{
187 ASSERT_TRUE(profile_dir_
.CreateUniqueTempDir());
188 ImportedMediaGalleryRegistry::GetInstance()->Initialize();
190 scoped_refptr
<storage::SpecialStoragePolicy
> storage_policy
=
191 new content::MockSpecialStoragePolicy();
193 // Initialize fake IPhotoDataProvider on media task runner thread.
194 MediaFileSystemBackend::MediaTaskRunner()->PostTask(
196 base::Bind(&IPhotoFileUtilTest::SetUpDataProvider
,
197 base::Unretained(this)));
198 base::WaitableEvent
event(true, false /* initially_signalled */);
199 MediaFileSystemBackend::MediaTaskRunner()->PostTask(
201 base::Bind(&base::WaitableEvent::Signal
, base::Unretained(&event
)));
204 media_path_filter_
.reset(new MediaPathFilter());
205 ScopedVector
<storage::FileSystemBackend
> additional_providers
;
206 additional_providers
.push_back(new TestMediaFileSystemBackend(
208 new TestIPhotoFileUtil(media_path_filter_
.get(),
209 iphoto_data_provider_
.get())));
211 file_system_context_
= new storage::FileSystemContext(
212 base::ThreadTaskRunnerHandle::Get().get(),
213 base::ThreadTaskRunnerHandle::Get().get(),
214 storage::ExternalMountPoints::CreateRefCounted().get(),
215 storage_policy
.get(),
217 additional_providers
.Pass(),
218 std::vector
<storage::URLRequestAutoMountHandler
>(),
220 content::CreateAllowFileAccessOptions());
224 void TestNonexistentFolder(const std::string
& path_append
) {
225 FileSystemOperation::FileEntryList contents
;
226 FileSystemURL url
= CreateURL(path_append
);
227 bool completed
= false;
228 ReadDirectoryTestHelper(operation_runner(), url
, &contents
, &completed
);
230 ASSERT_FALSE(completed
);
233 FileSystemURL
CreateURL(const std::string
& path
) const {
234 base::FilePath virtual_path
=
235 ImportedMediaGalleryRegistry::GetInstance()->ImportedRoot();
236 virtual_path
= virtual_path
.AppendASCII("iphoto");
237 virtual_path
= virtual_path
.AppendASCII(path
);
238 return file_system_context_
->CreateCrackedFileSystemURL(
239 GURL("http://www.example.com"),
240 storage::kFileSystemTypeIphoto
,
244 storage::FileSystemOperationRunner
* operation_runner() const {
245 return file_system_context_
->operation_runner();
248 scoped_refptr
<storage::FileSystemContext
> file_system_context() const {
249 return file_system_context_
;
252 TestIPhotoDataProvider
* data_provider() const {
253 return iphoto_data_provider_
.get();
257 base::MessageLoop message_loop_
;
258 content::TestBrowserThread io_thread_
;
260 base::ScopedTempDir profile_dir_
;
261 base::ScopedTempDir fake_library_dir_
;
263 scoped_refptr
<storage::FileSystemContext
> file_system_context_
;
264 scoped_ptr
<MediaPathFilter
> media_path_filter_
;
265 scoped_ptr
<TestIPhotoDataProvider
> iphoto_data_provider_
;
267 DISALLOW_COPY_AND_ASSIGN(IPhotoFileUtilTest
);
270 TEST_F(IPhotoFileUtilTest
, RootContents
) {
271 FileSystemOperation::FileEntryList contents
;
272 FileSystemURL url
= CreateURL("");
273 bool completed
= false;
274 ReadDirectoryTestHelper(operation_runner(), url
, &contents
, &completed
);
276 ASSERT_TRUE(completed
);
277 ASSERT_EQ(1u, contents
.size());
279 EXPECT_TRUE(contents
.front().is_directory
);
281 EXPECT_EQ(base::FilePath::FromUTF8Unsafe(kIPhotoAlbumsDir
).value(),
282 contents
.back().name
);
285 TEST_F(IPhotoFileUtilTest
, AlbumsDirectoryContents
) {
286 FileSystemOperation::FileEntryList contents
;
287 FileSystemURL url
= CreateURL(kIPhotoAlbumsDir
);
288 bool completed
= false;
289 ReadDirectoryTestHelper(operation_runner(), url
, &contents
, &completed
);
291 ASSERT_TRUE(completed
);
292 ASSERT_EQ(2u, contents
.size());
294 EXPECT_TRUE(contents
.front().is_directory
);
296 EXPECT_EQ("Album1", contents
.front().name
);
297 EXPECT_EQ("has_originals", contents
.back().name
);
300 TEST_F(IPhotoFileUtilTest
, AlbumContents
) {
301 FileSystemOperation::FileEntryList contents
;
302 FileSystemURL url
= CreateURL(std::string(kIPhotoAlbumsDir
) + "/Album1");
303 bool completed
= false;
304 ReadDirectoryTestHelper(operation_runner(), url
, &contents
, &completed
);
306 ASSERT_TRUE(completed
);
307 ASSERT_EQ(1u, contents
.size());
309 EXPECT_FALSE(contents
.front().is_directory
);
311 EXPECT_EQ("a.jpg", contents
.back().name
);
314 TEST_F(IPhotoFileUtilTest
, BadAccess
) {
315 FileSystemOperation::FileEntryList contents
;
316 FileSystemURL url
= CreateURL("None");
317 bool completed
= false;
318 ReadDirectoryTestHelper(operation_runner(), url
, &contents
, &completed
);
319 ASSERT_FALSE(completed
);
320 ASSERT_EQ(0u, contents
.size());
322 url
= CreateURL(std::string(kIPhotoAlbumsDir
) + "/NoAlbum");
324 ReadDirectoryTestHelper(operation_runner(), url
, &contents
, &completed
);
325 ASSERT_FALSE(completed
);
326 ASSERT_EQ(0u, contents
.size());
329 TEST_F(IPhotoFileUtilTest
, Originals
) {
330 FileSystemOperation::FileEntryList contents
;
332 CreateURL(std::string(kIPhotoAlbumsDir
) + "/has_originals");
333 bool completed
= false;
334 ReadDirectoryTestHelper(operation_runner(), url
, &contents
, &completed
);
336 ASSERT_TRUE(completed
);
337 ASSERT_EQ(2u, contents
.size());
338 EXPECT_TRUE(contents
.front().is_directory
);
339 EXPECT_EQ("Originals", contents
.front().name
);
340 EXPECT_FALSE(contents
.back().is_directory
);
341 EXPECT_EQ("a.jpg", contents
.back().name
);
343 url
= CreateURL(std::string(kIPhotoAlbumsDir
) + "/has_originals/Originals");
345 ReadDirectoryTestHelper(operation_runner(), url
, &contents
, &completed
);
346 ASSERT_TRUE(completed
);
347 ASSERT_EQ(1u, contents
.size());
349 EXPECT_FALSE(contents
.front().is_directory
);
350 EXPECT_EQ("a.jpg", contents
.front().name
);
353 } // namespace iphoto