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/location.h"
10 #include "base/run_loop.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "content/public/test/async_file_test_helper.h"
14 #include "content/public/test/mock_special_storage_policy.h"
15 #include "content/public/test/test_file_system_backend.h"
16 #include "content/public/test/test_file_system_context.h"
17 #include "storage/browser/blob/shareable_file_reference.h"
18 #include "storage/browser/fileapi/copy_or_move_file_validator.h"
19 #include "storage/browser/fileapi/external_mount_points.h"
20 #include "storage/browser/fileapi/file_system_backend.h"
21 #include "storage/browser/fileapi/file_system_context.h"
22 #include "storage/browser/fileapi/file_system_url.h"
23 #include "storage/browser/fileapi/isolated_context.h"
24 #include "storage/common/fileapi/file_system_util.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 using content::AsyncFileTestHelper
;
28 using storage::CopyOrMoveFileValidator
;
29 using storage::CopyOrMoveFileValidatorFactory
;
30 using storage::FileSystemURL
;
36 const storage::FileSystemType kNoValidatorType
=
37 storage::kFileSystemTypeTemporary
;
38 const storage::FileSystemType kWithValidatorType
= storage::kFileSystemTypeTest
;
40 void ExpectOk(const GURL
& origin_url
,
41 const std::string
& name
,
42 base::File::Error error
) {
43 ASSERT_EQ(base::File::FILE_OK
, error
);
46 class CopyOrMoveFileValidatorTestHelper
{
48 CopyOrMoveFileValidatorTestHelper(const GURL
& origin
,
49 storage::FileSystemType src_type
,
50 storage::FileSystemType dest_type
)
51 : origin_(origin
), src_type_(src_type
), dest_type_(dest_type
) {}
53 ~CopyOrMoveFileValidatorTestHelper() {
54 file_system_context_
= NULL
;
55 base::RunLoop().RunUntilIdle();
59 ASSERT_TRUE(base_
.CreateUniqueTempDir());
60 base::FilePath base_dir
= base_
.path();
62 file_system_context_
= CreateFileSystemContextForTesting(NULL
, base_dir
);
64 // Set up TestFileSystemBackend to require CopyOrMoveFileValidator.
65 storage::FileSystemBackend
* test_file_system_backend
=
66 file_system_context_
->GetFileSystemBackend(kWithValidatorType
);
67 static_cast<TestFileSystemBackend
*>(test_file_system_backend
)->
68 set_require_copy_or_move_validator(true);
71 storage::FileSystemBackend
* src_file_system_backend
=
72 file_system_context_
->GetFileSystemBackend(src_type_
);
73 src_file_system_backend
->ResolveURL(
74 FileSystemURL::CreateForTest(origin_
, src_type_
, base::FilePath()),
75 storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT
,
76 base::Bind(&ExpectOk
));
77 base::RunLoop().RunUntilIdle();
78 ASSERT_EQ(base::File::FILE_OK
, CreateDirectory(SourceURL("")));
81 DCHECK_EQ(kWithValidatorType
, dest_type_
);
82 ASSERT_EQ(base::File::FILE_OK
, CreateDirectory(DestURL("")));
84 copy_src_
= SourceURL("copy_src.jpg");
85 move_src_
= SourceURL("move_src.jpg");
86 copy_dest_
= DestURL("copy_dest.jpg");
87 move_dest_
= DestURL("move_dest.jpg");
89 ASSERT_EQ(base::File::FILE_OK
, CreateFile(copy_src_
, 10));
90 ASSERT_EQ(base::File::FILE_OK
, CreateFile(move_src_
, 10));
92 ASSERT_TRUE(FileExists(copy_src_
, 10));
93 ASSERT_TRUE(FileExists(move_src_
, 10));
94 ASSERT_FALSE(FileExists(copy_dest_
, 10));
95 ASSERT_FALSE(FileExists(move_dest_
, 10));
98 void SetMediaCopyOrMoveFileValidatorFactory(
99 scoped_ptr
<storage::CopyOrMoveFileValidatorFactory
> factory
) {
100 TestFileSystemBackend
* backend
= static_cast<TestFileSystemBackend
*>(
101 file_system_context_
->GetFileSystemBackend(kWithValidatorType
));
102 backend
->InitializeCopyOrMoveFileValidatorFactory(factory
.Pass());
105 void CopyTest(base::File::Error expected
) {
106 ASSERT_TRUE(FileExists(copy_src_
, 10));
107 ASSERT_FALSE(FileExists(copy_dest_
, 10));
110 AsyncFileTestHelper::Copy(
111 file_system_context_
.get(), copy_src_
, copy_dest_
));
113 EXPECT_TRUE(FileExists(copy_src_
, 10));
114 if (expected
== base::File::FILE_OK
)
115 EXPECT_TRUE(FileExists(copy_dest_
, 10));
117 EXPECT_FALSE(FileExists(copy_dest_
, 10));
120 void MoveTest(base::File::Error expected
) {
121 ASSERT_TRUE(FileExists(move_src_
, 10));
122 ASSERT_FALSE(FileExists(move_dest_
, 10));
125 AsyncFileTestHelper::Move(
126 file_system_context_
.get(), move_src_
, move_dest_
));
128 if (expected
== base::File::FILE_OK
) {
129 EXPECT_FALSE(FileExists(move_src_
, 10));
130 EXPECT_TRUE(FileExists(move_dest_
, 10));
132 EXPECT_TRUE(FileExists(move_src_
, 10));
133 EXPECT_FALSE(FileExists(move_dest_
, 10));
138 FileSystemURL
SourceURL(const std::string
& path
) {
139 return file_system_context_
->CreateCrackedFileSystemURL(
141 base::FilePath().AppendASCII("src").AppendASCII(path
));
144 FileSystemURL
DestURL(const std::string
& path
) {
145 return file_system_context_
->CreateCrackedFileSystemURL(
147 base::FilePath().AppendASCII("dest").AppendASCII(path
));
150 base::File::Error
CreateFile(const FileSystemURL
& url
, size_t size
) {
151 base::File::Error result
=
152 AsyncFileTestHelper::CreateFile(file_system_context_
.get(), url
);
153 if (result
!= base::File::FILE_OK
)
155 return AsyncFileTestHelper::TruncateFile(
156 file_system_context_
.get(), url
, size
);
159 base::File::Error
CreateDirectory(const FileSystemURL
& url
) {
160 return AsyncFileTestHelper::CreateDirectory(file_system_context_
.get(),
164 bool FileExists(const FileSystemURL
& url
, int64 expected_size
) {
165 return AsyncFileTestHelper::FileExists(
166 file_system_context_
.get(), url
, expected_size
);
169 base::ScopedTempDir base_
;
173 const storage::FileSystemType src_type_
;
174 const storage::FileSystemType dest_type_
;
175 std::string src_fsid_
;
176 std::string dest_fsid_
;
178 base::MessageLoop message_loop_
;
179 scoped_refptr
<storage::FileSystemContext
> file_system_context_
;
181 FileSystemURL copy_src_
;
182 FileSystemURL copy_dest_
;
183 FileSystemURL move_src_
;
184 FileSystemURL move_dest_
;
186 DISALLOW_COPY_AND_ASSIGN(CopyOrMoveFileValidatorTestHelper
);
189 // For TestCopyOrMoveFileValidatorFactory
196 class TestCopyOrMoveFileValidatorFactory
197 : public storage::CopyOrMoveFileValidatorFactory
{
199 // A factory that creates validators that accept everything or nothing.
200 // TODO(gbillock): switch args to enum or something
201 explicit TestCopyOrMoveFileValidatorFactory(Validity validity
)
202 : validity_(validity
) {}
203 ~TestCopyOrMoveFileValidatorFactory() override
{}
205 storage::CopyOrMoveFileValidator
* CreateCopyOrMoveFileValidator(
206 const FileSystemURL
& /*src_url*/,
207 const base::FilePath
& /*platform_path*/) override
{
208 return new TestCopyOrMoveFileValidator(validity_
);
212 class TestCopyOrMoveFileValidator
: public CopyOrMoveFileValidator
{
214 explicit TestCopyOrMoveFileValidator(Validity validity
)
215 : result_(validity
== VALID
|| validity
== POST_WRITE_INVALID
?
216 base::File::FILE_OK
:
217 base::File::FILE_ERROR_SECURITY
),
218 write_result_(validity
== VALID
|| validity
== PRE_WRITE_INVALID
?
219 base::File::FILE_OK
:
220 base::File::FILE_ERROR_SECURITY
) {
222 ~TestCopyOrMoveFileValidator() override
{}
224 void StartPreWriteValidation(
225 const ResultCallback
& result_callback
) override
{
226 // Post the result since a real validator must do work asynchronously.
227 base::ThreadTaskRunnerHandle::Get()->PostTask(
228 FROM_HERE
, base::Bind(result_callback
, result_
));
231 void StartPostWriteValidation(
232 const base::FilePath
& dest_platform_path
,
233 const ResultCallback
& result_callback
) override
{
234 // Post the result since a real validator must do work asynchronously.
235 base::ThreadTaskRunnerHandle::Get()->PostTask(
236 FROM_HERE
, base::Bind(result_callback
, write_result_
));
240 base::File::Error result_
;
241 base::File::Error write_result_
;
243 DISALLOW_COPY_AND_ASSIGN(TestCopyOrMoveFileValidator
);
248 DISALLOW_COPY_AND_ASSIGN(TestCopyOrMoveFileValidatorFactory
);
253 TEST(CopyOrMoveFileValidatorTest
, NoValidatorWithinSameFSType
) {
254 // Within a file system type, validation is not expected, so it should
255 // work for kWithValidatorType without a validator set.
256 CopyOrMoveFileValidatorTestHelper
helper(GURL("http://foo"),
260 helper
.CopyTest(base::File::FILE_OK
);
261 helper
.MoveTest(base::File::FILE_OK
);
264 TEST(CopyOrMoveFileValidatorTest
, MissingValidator
) {
265 // Copying or moving into a kWithValidatorType requires a file
266 // validator. An error is expected if copy is attempted without a validator.
267 CopyOrMoveFileValidatorTestHelper
helper(GURL("http://foo"),
271 helper
.CopyTest(base::File::FILE_ERROR_SECURITY
);
272 helper
.MoveTest(base::File::FILE_ERROR_SECURITY
);
275 TEST(CopyOrMoveFileValidatorTest
, AcceptAll
) {
276 CopyOrMoveFileValidatorTestHelper
helper(GURL("http://foo"),
280 scoped_ptr
<CopyOrMoveFileValidatorFactory
> factory(
281 new TestCopyOrMoveFileValidatorFactory(VALID
));
282 helper
.SetMediaCopyOrMoveFileValidatorFactory(factory
.Pass());
284 helper
.CopyTest(base::File::FILE_OK
);
285 helper
.MoveTest(base::File::FILE_OK
);
288 TEST(CopyOrMoveFileValidatorTest
, AcceptNone
) {
289 CopyOrMoveFileValidatorTestHelper
helper(GURL("http://foo"),
293 scoped_ptr
<CopyOrMoveFileValidatorFactory
> factory(
294 new TestCopyOrMoveFileValidatorFactory(PRE_WRITE_INVALID
));
295 helper
.SetMediaCopyOrMoveFileValidatorFactory(factory
.Pass());
297 helper
.CopyTest(base::File::FILE_ERROR_SECURITY
);
298 helper
.MoveTest(base::File::FILE_ERROR_SECURITY
);
301 TEST(CopyOrMoveFileValidatorTest
, OverrideValidator
) {
302 // Once set, you can not override the validator.
303 CopyOrMoveFileValidatorTestHelper
helper(GURL("http://foo"),
307 scoped_ptr
<CopyOrMoveFileValidatorFactory
> reject_factory(
308 new TestCopyOrMoveFileValidatorFactory(PRE_WRITE_INVALID
));
309 helper
.SetMediaCopyOrMoveFileValidatorFactory(reject_factory
.Pass());
311 scoped_ptr
<CopyOrMoveFileValidatorFactory
> accept_factory(
312 new TestCopyOrMoveFileValidatorFactory(VALID
));
313 helper
.SetMediaCopyOrMoveFileValidatorFactory(accept_factory
.Pass());
315 helper
.CopyTest(base::File::FILE_ERROR_SECURITY
);
316 helper
.MoveTest(base::File::FILE_ERROR_SECURITY
);
319 TEST(CopyOrMoveFileValidatorTest
, RejectPostWrite
) {
320 CopyOrMoveFileValidatorTestHelper
helper(GURL("http://foo"),
324 scoped_ptr
<CopyOrMoveFileValidatorFactory
> factory(
325 new TestCopyOrMoveFileValidatorFactory(POST_WRITE_INVALID
));
326 helper
.SetMediaCopyOrMoveFileValidatorFactory(factory
.Pass());
328 helper
.CopyTest(base::File::FILE_ERROR_SECURITY
);
329 helper
.MoveTest(base::File::FILE_ERROR_SECURITY
);
332 } // namespace content