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/synchronization/waitable_event.h"
16 #include "base/time/time.h"
17 #include "chrome/browser/media_galleries/fileapi/iphoto_data_provider.h"
18 #include "chrome/browser/media_galleries/fileapi/iphoto_file_util.h"
19 #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
20 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
21 #include "chrome/browser/media_galleries/imported_media_gallery_registry.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "content/public/test/mock_special_storage_policy.h"
24 #include "content/public/test/test_browser_thread.h"
25 #include "content/public/test/test_file_system_options.h"
26 #include "storage/browser/fileapi/async_file_util.h"
27 #include "storage/browser/fileapi/external_mount_points.h"
28 #include "storage/browser/fileapi/file_system_context.h"
29 #include "storage/browser/fileapi/file_system_operation_context.h"
30 #include "storage/browser/fileapi/file_system_operation_runner.h"
31 #include "testing/gtest/include/gtest/gtest.h"
33 using storage::FileSystemOperationContext
;
34 using storage::FileSystemOperation
;
35 using storage::FileSystemURL
;
41 void ReadDirectoryTestHelperCallback(
42 base::RunLoop
* run_loop
,
43 FileSystemOperation::FileEntryList
* contents
,
45 base::File::Error error
,
46 const FileSystemOperation::FileEntryList
& file_list
,
49 *completed
= !has_more
&& error
== base::File::FILE_OK
;
50 *contents
= file_list
;
54 void ReadDirectoryTestHelper(storage::FileSystemOperationRunner
* runner
,
55 const FileSystemURL
& url
,
56 FileSystemOperation::FileEntryList
* contents
,
60 base::RunLoop run_loop
;
61 runner
->ReadDirectory(
62 url
, base::Bind(&ReadDirectoryTestHelperCallback
, &run_loop
, contents
,
69 class TestIPhotoDataProvider
: public IPhotoDataProvider
{
71 explicit TestIPhotoDataProvider(const base::FilePath
& fake_library_path
)
72 : IPhotoDataProvider(fake_library_path
) {
73 EXPECT_TRUE(fake_auto_add_dir_
.CreateUniqueTempDir());
76 ~TestIPhotoDataProvider() override
{}
78 void RefreshData(const ReadyCallback
& ready_callback
) override
{
79 ready_callback
.Run(true /* success */);
82 std::vector
<std::string
> GetAlbumNames() const override
{
83 std::vector
<std::string
> names
;
84 names
.push_back("Album1");
85 names
.push_back("has_originals");
89 std::map
<std::string
, base::FilePath
> GetAlbumContents(
90 const std::string
& album
) const override
{
91 std::map
<std::string
, base::FilePath
> contents
;
92 contents
["a.jpg"] = library_path().AppendASCII("a.jpg");
96 base::FilePath
GetPhotoLocationInAlbum(
97 const std::string
& album
,
98 const std::string
& filename
) const override
{
99 return library_path().AppendASCII("a.jpg");
102 bool HasOriginals(const std::string
& album
) const override
{
103 return (album
== "has_originals");
106 std::map
<std::string
, base::FilePath
> GetOriginals(
107 const std::string
& album
) const override
{
108 std::map
<std::string
, base::FilePath
> contents
;
109 contents
["a.jpg"] = library_path().AppendASCII("orig.jpg");
113 base::FilePath
GetOriginalPhotoLocation(
114 const std::string
& album
,
115 const std::string
& filename
) const override
{
116 return library_path().AppendASCII("orig.jpg");
120 base::ScopedTempDir fake_auto_add_dir_
;
123 class TestIPhotoFileUtil
: public IPhotoFileUtil
{
125 explicit TestIPhotoFileUtil(MediaPathFilter
* media_path_filter
,
126 IPhotoDataProvider
* data_provider
)
127 : IPhotoFileUtil(media_path_filter
),
128 data_provider_(data_provider
) {
130 ~TestIPhotoFileUtil() override
{}
133 IPhotoDataProvider
* GetDataProvider() override
{ return data_provider_
; }
135 IPhotoDataProvider
* data_provider_
;
138 class TestMediaFileSystemBackend
: public MediaFileSystemBackend
{
140 TestMediaFileSystemBackend(const base::FilePath
& profile_path
,
141 IPhotoFileUtil
* iphoto_file_util
)
142 : MediaFileSystemBackend(
144 MediaFileSystemBackend::MediaTaskRunner().get()),
145 test_file_util_(iphoto_file_util
) {}
147 storage::AsyncFileUtil
* GetAsyncFileUtil(
148 storage::FileSystemType type
) override
{
149 if (type
!= storage::kFileSystemTypeIphoto
)
152 return test_file_util_
.get();
156 scoped_ptr
<storage::AsyncFileUtil
> test_file_util_
;
159 class IPhotoFileUtilTest
: public testing::Test
{
162 : io_thread_(content::BrowserThread::IO
, &message_loop_
) {
165 void SetUpDataProvider() {
166 ASSERT_TRUE(fake_library_dir_
.CreateUniqueTempDir());
170 fake_library_dir_
.path().AppendASCII("a.jpg"),
176 fake_library_dir_
.path().AppendASCII("orig.jpg"),
180 iphoto_data_provider_
.reset(
181 new TestIPhotoDataProvider(fake_library_dir_
.path()));
184 void SetUp() override
{
185 ASSERT_TRUE(profile_dir_
.CreateUniqueTempDir());
186 ImportedMediaGalleryRegistry::GetInstance()->Initialize();
188 scoped_refptr
<storage::SpecialStoragePolicy
> storage_policy
=
189 new content::MockSpecialStoragePolicy();
191 // Initialize fake IPhotoDataProvider on media task runner thread.
192 MediaFileSystemBackend::MediaTaskRunner()->PostTask(
194 base::Bind(&IPhotoFileUtilTest::SetUpDataProvider
,
195 base::Unretained(this)));
196 base::WaitableEvent
event(true, false /* initially_signalled */);
197 MediaFileSystemBackend::MediaTaskRunner()->PostTask(
199 base::Bind(&base::WaitableEvent::Signal
, base::Unretained(&event
)));
202 media_path_filter_
.reset(new MediaPathFilter());
203 ScopedVector
<storage::FileSystemBackend
> additional_providers
;
204 additional_providers
.push_back(new TestMediaFileSystemBackend(
206 new TestIPhotoFileUtil(media_path_filter_
.get(),
207 iphoto_data_provider_
.get())));
209 file_system_context_
= new storage::FileSystemContext(
210 base::MessageLoopProxy::current().get(),
211 base::MessageLoopProxy::current().get(),
212 storage::ExternalMountPoints::CreateRefCounted().get(),
213 storage_policy
.get(),
215 additional_providers
.Pass(),
216 std::vector
<storage::URLRequestAutoMountHandler
>(),
218 content::CreateAllowFileAccessOptions());
222 void TestNonexistentFolder(const std::string
& path_append
) {
223 FileSystemOperation::FileEntryList contents
;
224 FileSystemURL url
= CreateURL(path_append
);
225 bool completed
= false;
226 ReadDirectoryTestHelper(operation_runner(), url
, &contents
, &completed
);
228 ASSERT_FALSE(completed
);
231 FileSystemURL
CreateURL(const std::string
& path
) const {
232 base::FilePath virtual_path
=
233 ImportedMediaGalleryRegistry::GetInstance()->ImportedRoot();
234 virtual_path
= virtual_path
.AppendASCII("iphoto");
235 virtual_path
= virtual_path
.AppendASCII(path
);
236 return file_system_context_
->CreateCrackedFileSystemURL(
237 GURL("http://www.example.com"),
238 storage::kFileSystemTypeIphoto
,
242 storage::FileSystemOperationRunner
* operation_runner() const {
243 return file_system_context_
->operation_runner();
246 scoped_refptr
<storage::FileSystemContext
> file_system_context() const {
247 return file_system_context_
;
250 TestIPhotoDataProvider
* data_provider() const {
251 return iphoto_data_provider_
.get();
255 base::MessageLoop message_loop_
;
256 content::TestBrowserThread io_thread_
;
258 base::ScopedTempDir profile_dir_
;
259 base::ScopedTempDir fake_library_dir_
;
261 scoped_refptr
<storage::FileSystemContext
> file_system_context_
;
262 scoped_ptr
<MediaPathFilter
> media_path_filter_
;
263 scoped_ptr
<TestIPhotoDataProvider
> iphoto_data_provider_
;
265 DISALLOW_COPY_AND_ASSIGN(IPhotoFileUtilTest
);
268 TEST_F(IPhotoFileUtilTest
, RootContents
) {
269 FileSystemOperation::FileEntryList contents
;
270 FileSystemURL url
= CreateURL("");
271 bool completed
= false;
272 ReadDirectoryTestHelper(operation_runner(), url
, &contents
, &completed
);
274 ASSERT_TRUE(completed
);
275 ASSERT_EQ(1u, contents
.size());
277 EXPECT_TRUE(contents
.front().is_directory
);
279 EXPECT_EQ(base::FilePath::FromUTF8Unsafe(kIPhotoAlbumsDir
).value(),
280 contents
.back().name
);
283 TEST_F(IPhotoFileUtilTest
, AlbumsDirectoryContents
) {
284 FileSystemOperation::FileEntryList contents
;
285 FileSystemURL url
= CreateURL(kIPhotoAlbumsDir
);
286 bool completed
= false;
287 ReadDirectoryTestHelper(operation_runner(), url
, &contents
, &completed
);
289 ASSERT_TRUE(completed
);
290 ASSERT_EQ(2u, contents
.size());
292 EXPECT_TRUE(contents
.front().is_directory
);
294 EXPECT_EQ("Album1", contents
.front().name
);
295 EXPECT_EQ("has_originals", contents
.back().name
);
298 TEST_F(IPhotoFileUtilTest
, AlbumContents
) {
299 FileSystemOperation::FileEntryList contents
;
300 FileSystemURL url
= CreateURL(std::string(kIPhotoAlbumsDir
) + "/Album1");
301 bool completed
= false;
302 ReadDirectoryTestHelper(operation_runner(), url
, &contents
, &completed
);
304 ASSERT_TRUE(completed
);
305 ASSERT_EQ(1u, contents
.size());
307 EXPECT_FALSE(contents
.front().is_directory
);
309 EXPECT_EQ("a.jpg", contents
.back().name
);
312 TEST_F(IPhotoFileUtilTest
, BadAccess
) {
313 FileSystemOperation::FileEntryList contents
;
314 FileSystemURL url
= CreateURL("None");
315 bool completed
= false;
316 ReadDirectoryTestHelper(operation_runner(), url
, &contents
, &completed
);
317 ASSERT_FALSE(completed
);
318 ASSERT_EQ(0u, contents
.size());
320 url
= CreateURL(std::string(kIPhotoAlbumsDir
) + "/NoAlbum");
322 ReadDirectoryTestHelper(operation_runner(), url
, &contents
, &completed
);
323 ASSERT_FALSE(completed
);
324 ASSERT_EQ(0u, contents
.size());
327 TEST_F(IPhotoFileUtilTest
, Originals
) {
328 FileSystemOperation::FileEntryList contents
;
330 CreateURL(std::string(kIPhotoAlbumsDir
) + "/has_originals");
331 bool completed
= false;
332 ReadDirectoryTestHelper(operation_runner(), url
, &contents
, &completed
);
334 ASSERT_TRUE(completed
);
335 ASSERT_EQ(2u, contents
.size());
336 EXPECT_TRUE(contents
.front().is_directory
);
337 EXPECT_EQ("Originals", contents
.front().name
);
338 EXPECT_FALSE(contents
.back().is_directory
);
339 EXPECT_EQ("a.jpg", contents
.back().name
);
341 url
= CreateURL(std::string(kIPhotoAlbumsDir
) + "/has_originals/Originals");
343 ReadDirectoryTestHelper(operation_runner(), url
, &contents
, &completed
);
344 ASSERT_TRUE(completed
);
345 ASSERT_EQ(1u, contents
.size());
347 EXPECT_FALSE(contents
.front().is_directory
);
348 EXPECT_EQ("a.jpg", contents
.front().name
);
351 } // namespace iphoto