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.
5 #include "base/basictypes.h"
7 #include "base/files/file_path.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/run_loop.h"
10 #include "content/public/test/async_file_test_helper.h"
11 #include "content/public/test/mock_special_storage_policy.h"
12 #include "content/public/test/test_file_system_backend.h"
13 #include "content/public/test/test_file_system_context.h"
14 #include "storage/browser/blob/shareable_file_reference.h"
15 #include "storage/browser/fileapi/copy_or_move_file_validator.h"
16 #include "storage/browser/fileapi/external_mount_points.h"
17 #include "storage/browser/fileapi/file_system_backend.h"
18 #include "storage/browser/fileapi/file_system_context.h"
19 #include "storage/browser/fileapi/file_system_url.h"
20 #include "storage/browser/fileapi/isolated_context.h"
21 #include "storage/common/fileapi/file_system_util.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 using content::AsyncFileTestHelper
;
25 using storage::CopyOrMoveFileValidator
;
26 using storage::CopyOrMoveFileValidatorFactory
;
27 using storage::FileSystemURL
;
33 const storage::FileSystemType kNoValidatorType
=
34 storage::kFileSystemTypeTemporary
;
35 const storage::FileSystemType kWithValidatorType
= storage::kFileSystemTypeTest
;
37 void ExpectOk(const GURL
& origin_url
,
38 const std::string
& name
,
39 base::File::Error error
) {
40 ASSERT_EQ(base::File::FILE_OK
, error
);
43 class CopyOrMoveFileValidatorTestHelper
{
45 CopyOrMoveFileValidatorTestHelper(const GURL
& origin
,
46 storage::FileSystemType src_type
,
47 storage::FileSystemType dest_type
)
48 : origin_(origin
), src_type_(src_type
), dest_type_(dest_type
) {}
50 ~CopyOrMoveFileValidatorTestHelper() {
51 file_system_context_
= NULL
;
52 base::RunLoop().RunUntilIdle();
56 ASSERT_TRUE(base_
.CreateUniqueTempDir());
57 base::FilePath base_dir
= base_
.path();
59 file_system_context_
= CreateFileSystemContextForTesting(NULL
, base_dir
);
61 // Set up TestFileSystemBackend to require CopyOrMoveFileValidator.
62 storage::FileSystemBackend
* test_file_system_backend
=
63 file_system_context_
->GetFileSystemBackend(kWithValidatorType
);
64 static_cast<TestFileSystemBackend
*>(test_file_system_backend
)->
65 set_require_copy_or_move_validator(true);
68 storage::FileSystemBackend
* src_file_system_backend
=
69 file_system_context_
->GetFileSystemBackend(src_type_
);
70 src_file_system_backend
->ResolveURL(
71 FileSystemURL::CreateForTest(origin_
, src_type_
, base::FilePath()),
72 storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT
,
73 base::Bind(&ExpectOk
));
74 base::RunLoop().RunUntilIdle();
75 ASSERT_EQ(base::File::FILE_OK
, CreateDirectory(SourceURL("")));
78 DCHECK_EQ(kWithValidatorType
, dest_type_
);
79 ASSERT_EQ(base::File::FILE_OK
, CreateDirectory(DestURL("")));
81 copy_src_
= SourceURL("copy_src.jpg");
82 move_src_
= SourceURL("move_src.jpg");
83 copy_dest_
= DestURL("copy_dest.jpg");
84 move_dest_
= DestURL("move_dest.jpg");
86 ASSERT_EQ(base::File::FILE_OK
, CreateFile(copy_src_
, 10));
87 ASSERT_EQ(base::File::FILE_OK
, CreateFile(move_src_
, 10));
89 ASSERT_TRUE(FileExists(copy_src_
, 10));
90 ASSERT_TRUE(FileExists(move_src_
, 10));
91 ASSERT_FALSE(FileExists(copy_dest_
, 10));
92 ASSERT_FALSE(FileExists(move_dest_
, 10));
95 void SetMediaCopyOrMoveFileValidatorFactory(
96 scoped_ptr
<storage::CopyOrMoveFileValidatorFactory
> factory
) {
97 TestFileSystemBackend
* backend
= static_cast<TestFileSystemBackend
*>(
98 file_system_context_
->GetFileSystemBackend(kWithValidatorType
));
99 backend
->InitializeCopyOrMoveFileValidatorFactory(factory
.Pass());
102 void CopyTest(base::File::Error expected
) {
103 ASSERT_TRUE(FileExists(copy_src_
, 10));
104 ASSERT_FALSE(FileExists(copy_dest_
, 10));
107 AsyncFileTestHelper::Copy(
108 file_system_context_
.get(), copy_src_
, copy_dest_
));
110 EXPECT_TRUE(FileExists(copy_src_
, 10));
111 if (expected
== base::File::FILE_OK
)
112 EXPECT_TRUE(FileExists(copy_dest_
, 10));
114 EXPECT_FALSE(FileExists(copy_dest_
, 10));
117 void MoveTest(base::File::Error expected
) {
118 ASSERT_TRUE(FileExists(move_src_
, 10));
119 ASSERT_FALSE(FileExists(move_dest_
, 10));
122 AsyncFileTestHelper::Move(
123 file_system_context_
.get(), move_src_
, move_dest_
));
125 if (expected
== base::File::FILE_OK
) {
126 EXPECT_FALSE(FileExists(move_src_
, 10));
127 EXPECT_TRUE(FileExists(move_dest_
, 10));
129 EXPECT_TRUE(FileExists(move_src_
, 10));
130 EXPECT_FALSE(FileExists(move_dest_
, 10));
135 FileSystemURL
SourceURL(const std::string
& path
) {
136 return file_system_context_
->CreateCrackedFileSystemURL(
138 base::FilePath().AppendASCII("src").AppendASCII(path
));
141 FileSystemURL
DestURL(const std::string
& path
) {
142 return file_system_context_
->CreateCrackedFileSystemURL(
144 base::FilePath().AppendASCII("dest").AppendASCII(path
));
147 base::File::Error
CreateFile(const FileSystemURL
& url
, size_t size
) {
148 base::File::Error result
=
149 AsyncFileTestHelper::CreateFile(file_system_context_
.get(), url
);
150 if (result
!= base::File::FILE_OK
)
152 return AsyncFileTestHelper::TruncateFile(
153 file_system_context_
.get(), url
, size
);
156 base::File::Error
CreateDirectory(const FileSystemURL
& url
) {
157 return AsyncFileTestHelper::CreateDirectory(file_system_context_
.get(),
161 bool FileExists(const FileSystemURL
& url
, int64 expected_size
) {
162 return AsyncFileTestHelper::FileExists(
163 file_system_context_
.get(), url
, expected_size
);
166 base::ScopedTempDir base_
;
170 const storage::FileSystemType src_type_
;
171 const storage::FileSystemType dest_type_
;
172 std::string src_fsid_
;
173 std::string dest_fsid_
;
175 base::MessageLoop message_loop_
;
176 scoped_refptr
<storage::FileSystemContext
> file_system_context_
;
178 FileSystemURL copy_src_
;
179 FileSystemURL copy_dest_
;
180 FileSystemURL move_src_
;
181 FileSystemURL move_dest_
;
183 DISALLOW_COPY_AND_ASSIGN(CopyOrMoveFileValidatorTestHelper
);
186 // For TestCopyOrMoveFileValidatorFactory
193 class TestCopyOrMoveFileValidatorFactory
194 : public storage::CopyOrMoveFileValidatorFactory
{
196 // A factory that creates validators that accept everything or nothing.
197 // TODO(gbillock): switch args to enum or something
198 explicit TestCopyOrMoveFileValidatorFactory(Validity validity
)
199 : validity_(validity
) {}
200 ~TestCopyOrMoveFileValidatorFactory() override
{}
202 storage::CopyOrMoveFileValidator
* CreateCopyOrMoveFileValidator(
203 const FileSystemURL
& /*src_url*/,
204 const base::FilePath
& /*platform_path*/) override
{
205 return new TestCopyOrMoveFileValidator(validity_
);
209 class TestCopyOrMoveFileValidator
: public CopyOrMoveFileValidator
{
211 explicit TestCopyOrMoveFileValidator(Validity validity
)
212 : result_(validity
== VALID
|| validity
== POST_WRITE_INVALID
?
213 base::File::FILE_OK
:
214 base::File::FILE_ERROR_SECURITY
),
215 write_result_(validity
== VALID
|| validity
== PRE_WRITE_INVALID
?
216 base::File::FILE_OK
:
217 base::File::FILE_ERROR_SECURITY
) {
219 ~TestCopyOrMoveFileValidator() override
{}
221 void StartPreWriteValidation(
222 const ResultCallback
& result_callback
) override
{
223 // Post the result since a real validator must do work asynchronously.
224 base::MessageLoop::current()->PostTask(
225 FROM_HERE
, base::Bind(result_callback
, result_
));
228 void StartPostWriteValidation(
229 const base::FilePath
& dest_platform_path
,
230 const ResultCallback
& result_callback
) override
{
231 // Post the result since a real validator must do work asynchronously.
232 base::MessageLoop::current()->PostTask(
233 FROM_HERE
, base::Bind(result_callback
, write_result_
));
237 base::File::Error result_
;
238 base::File::Error write_result_
;
240 DISALLOW_COPY_AND_ASSIGN(TestCopyOrMoveFileValidator
);
245 DISALLOW_COPY_AND_ASSIGN(TestCopyOrMoveFileValidatorFactory
);
250 TEST(CopyOrMoveFileValidatorTest
, NoValidatorWithinSameFSType
) {
251 // Within a file system type, validation is not expected, so it should
252 // work for kWithValidatorType without a validator set.
253 CopyOrMoveFileValidatorTestHelper
helper(GURL("http://foo"),
257 helper
.CopyTest(base::File::FILE_OK
);
258 helper
.MoveTest(base::File::FILE_OK
);
261 TEST(CopyOrMoveFileValidatorTest
, MissingValidator
) {
262 // Copying or moving into a kWithValidatorType requires a file
263 // validator. An error is expected if copy is attempted without a validator.
264 CopyOrMoveFileValidatorTestHelper
helper(GURL("http://foo"),
268 helper
.CopyTest(base::File::FILE_ERROR_SECURITY
);
269 helper
.MoveTest(base::File::FILE_ERROR_SECURITY
);
272 TEST(CopyOrMoveFileValidatorTest
, AcceptAll
) {
273 CopyOrMoveFileValidatorTestHelper
helper(GURL("http://foo"),
277 scoped_ptr
<CopyOrMoveFileValidatorFactory
> factory(
278 new TestCopyOrMoveFileValidatorFactory(VALID
));
279 helper
.SetMediaCopyOrMoveFileValidatorFactory(factory
.Pass());
281 helper
.CopyTest(base::File::FILE_OK
);
282 helper
.MoveTest(base::File::FILE_OK
);
285 TEST(CopyOrMoveFileValidatorTest
, AcceptNone
) {
286 CopyOrMoveFileValidatorTestHelper
helper(GURL("http://foo"),
290 scoped_ptr
<CopyOrMoveFileValidatorFactory
> factory(
291 new TestCopyOrMoveFileValidatorFactory(PRE_WRITE_INVALID
));
292 helper
.SetMediaCopyOrMoveFileValidatorFactory(factory
.Pass());
294 helper
.CopyTest(base::File::FILE_ERROR_SECURITY
);
295 helper
.MoveTest(base::File::FILE_ERROR_SECURITY
);
298 TEST(CopyOrMoveFileValidatorTest
, OverrideValidator
) {
299 // Once set, you can not override the validator.
300 CopyOrMoveFileValidatorTestHelper
helper(GURL("http://foo"),
304 scoped_ptr
<CopyOrMoveFileValidatorFactory
> reject_factory(
305 new TestCopyOrMoveFileValidatorFactory(PRE_WRITE_INVALID
));
306 helper
.SetMediaCopyOrMoveFileValidatorFactory(reject_factory
.Pass());
308 scoped_ptr
<CopyOrMoveFileValidatorFactory
> accept_factory(
309 new TestCopyOrMoveFileValidatorFactory(VALID
));
310 helper
.SetMediaCopyOrMoveFileValidatorFactory(accept_factory
.Pass());
312 helper
.CopyTest(base::File::FILE_ERROR_SECURITY
);
313 helper
.MoveTest(base::File::FILE_ERROR_SECURITY
);
316 TEST(CopyOrMoveFileValidatorTest
, RejectPostWrite
) {
317 CopyOrMoveFileValidatorTestHelper
helper(GURL("http://foo"),
321 scoped_ptr
<CopyOrMoveFileValidatorFactory
> factory(
322 new TestCopyOrMoveFileValidatorFactory(POST_WRITE_INVALID
));
323 helper
.SetMediaCopyOrMoveFileValidatorFactory(factory
.Pass());
325 helper
.CopyTest(base::File::FILE_ERROR_SECURITY
);
326 helper
.MoveTest(base::File::FILE_ERROR_SECURITY
);
329 } // namespace content