• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "base/basictypes.h"
6 #include "base/bind.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/fileapi/copy_or_move_file_validator.h"
15 #include "storage/browser/fileapi/external_mount_points.h"
16 #include "storage/browser/fileapi/file_system_backend.h"
17 #include "storage/browser/fileapi/file_system_context.h"
18 #include "storage/browser/fileapi/file_system_url.h"
19 #include "storage/browser/fileapi/isolated_context.h"
20 #include "storage/common/blob/shareable_file_reference.h"
21 #include "storage/common/fileapi/file_system_util.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 
24 using content::AsyncFileTestHelper;
25 using storage::CopyOrMoveFileValidator;
26 using storage::CopyOrMoveFileValidatorFactory;
27 using storage::FileSystemURL;
28 
29 namespace content {
30 
31 namespace {
32 
33 const storage::FileSystemType kNoValidatorType =
34     storage::kFileSystemTypeTemporary;
35 const storage::FileSystemType kWithValidatorType = storage::kFileSystemTypeTest;
36 
ExpectOk(const GURL & origin_url,const std::string & name,base::File::Error error)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);
41 }
42 
43 class CopyOrMoveFileValidatorTestHelper {
44  public:
CopyOrMoveFileValidatorTestHelper(const GURL & origin,storage::FileSystemType src_type,storage::FileSystemType dest_type)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) {}
49 
~CopyOrMoveFileValidatorTestHelper()50   ~CopyOrMoveFileValidatorTestHelper() {
51     file_system_context_ = NULL;
52     base::RunLoop().RunUntilIdle();
53   }
54 
SetUp()55   void SetUp() {
56     ASSERT_TRUE(base_.CreateUniqueTempDir());
57     base::FilePath base_dir = base_.path();
58 
59     file_system_context_ = CreateFileSystemContextForTesting(NULL, base_dir);
60 
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);
66 
67     // Sets up source.
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("")));
76 
77     // Sets up dest.
78     DCHECK_EQ(kWithValidatorType, dest_type_);
79     ASSERT_EQ(base::File::FILE_OK, CreateDirectory(DestURL("")));
80 
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");
85 
86     ASSERT_EQ(base::File::FILE_OK, CreateFile(copy_src_, 10));
87     ASSERT_EQ(base::File::FILE_OK, CreateFile(move_src_, 10));
88 
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));
93   }
94 
SetMediaCopyOrMoveFileValidatorFactory(scoped_ptr<storage::CopyOrMoveFileValidatorFactory> factory)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());
100   }
101 
CopyTest(base::File::Error expected)102   void CopyTest(base::File::Error expected) {
103     ASSERT_TRUE(FileExists(copy_src_, 10));
104     ASSERT_FALSE(FileExists(copy_dest_, 10));
105 
106     EXPECT_EQ(expected,
107               AsyncFileTestHelper::Copy(
108                   file_system_context_.get(), copy_src_, copy_dest_));
109 
110     EXPECT_TRUE(FileExists(copy_src_, 10));
111     if (expected == base::File::FILE_OK)
112       EXPECT_TRUE(FileExists(copy_dest_, 10));
113     else
114       EXPECT_FALSE(FileExists(copy_dest_, 10));
115   };
116 
MoveTest(base::File::Error expected)117   void MoveTest(base::File::Error expected) {
118     ASSERT_TRUE(FileExists(move_src_, 10));
119     ASSERT_FALSE(FileExists(move_dest_, 10));
120 
121     EXPECT_EQ(expected,
122               AsyncFileTestHelper::Move(
123                   file_system_context_.get(), move_src_, move_dest_));
124 
125     if (expected == base::File::FILE_OK) {
126       EXPECT_FALSE(FileExists(move_src_, 10));
127       EXPECT_TRUE(FileExists(move_dest_, 10));
128     } else {
129       EXPECT_TRUE(FileExists(move_src_, 10));
130       EXPECT_FALSE(FileExists(move_dest_, 10));
131     }
132   };
133 
134  private:
SourceURL(const std::string & path)135   FileSystemURL SourceURL(const std::string& path) {
136     return file_system_context_->CreateCrackedFileSystemURL(
137         origin_, src_type_,
138         base::FilePath().AppendASCII("src").AppendASCII(path));
139   }
140 
DestURL(const std::string & path)141   FileSystemURL DestURL(const std::string& path) {
142     return file_system_context_->CreateCrackedFileSystemURL(
143         origin_, dest_type_,
144         base::FilePath().AppendASCII("dest").AppendASCII(path));
145   }
146 
CreateFile(const FileSystemURL & url,size_t size)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)
151       return result;
152     return AsyncFileTestHelper::TruncateFile(
153         file_system_context_.get(), url, size);
154   }
155 
CreateDirectory(const FileSystemURL & url)156   base::File::Error CreateDirectory(const FileSystemURL& url) {
157     return AsyncFileTestHelper::CreateDirectory(file_system_context_.get(),
158                                                 url);
159   }
160 
FileExists(const FileSystemURL & url,int64 expected_size)161   bool FileExists(const FileSystemURL& url, int64 expected_size) {
162     return AsyncFileTestHelper::FileExists(
163         file_system_context_.get(), url, expected_size);
164   }
165 
166   base::ScopedTempDir base_;
167 
168   const GURL origin_;
169 
170   const storage::FileSystemType src_type_;
171   const storage::FileSystemType dest_type_;
172   std::string src_fsid_;
173   std::string dest_fsid_;
174 
175   base::MessageLoop message_loop_;
176   scoped_refptr<storage::FileSystemContext> file_system_context_;
177 
178   FileSystemURL copy_src_;
179   FileSystemURL copy_dest_;
180   FileSystemURL move_src_;
181   FileSystemURL move_dest_;
182 
183   DISALLOW_COPY_AND_ASSIGN(CopyOrMoveFileValidatorTestHelper);
184 };
185 
186 // For TestCopyOrMoveFileValidatorFactory
187 enum Validity {
188   VALID,
189   PRE_WRITE_INVALID,
190   POST_WRITE_INVALID
191 };
192 
193 class TestCopyOrMoveFileValidatorFactory
194     : public storage::CopyOrMoveFileValidatorFactory {
195  public:
196   // A factory that creates validators that accept everything or nothing.
197   // TODO(gbillock): switch args to enum or something
TestCopyOrMoveFileValidatorFactory(Validity validity)198   explicit TestCopyOrMoveFileValidatorFactory(Validity validity)
199       : validity_(validity) {}
~TestCopyOrMoveFileValidatorFactory()200   virtual ~TestCopyOrMoveFileValidatorFactory() {}
201 
CreateCopyOrMoveFileValidator(const FileSystemURL &,const base::FilePath &)202   virtual storage::CopyOrMoveFileValidator* CreateCopyOrMoveFileValidator(
203       const FileSystemURL& /*src_url*/,
204       const base::FilePath& /*platform_path*/) OVERRIDE {
205     return new TestCopyOrMoveFileValidator(validity_);
206   }
207 
208  private:
209   class TestCopyOrMoveFileValidator : public CopyOrMoveFileValidator {
210    public:
TestCopyOrMoveFileValidator(Validity validity)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) {
218     }
~TestCopyOrMoveFileValidator()219     virtual ~TestCopyOrMoveFileValidator() {}
220 
StartPreWriteValidation(const ResultCallback & result_callback)221     virtual 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_));
226     }
227 
StartPostWriteValidation(const base::FilePath & dest_platform_path,const ResultCallback & result_callback)228     virtual 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_));
234     }
235 
236    private:
237     base::File::Error result_;
238     base::File::Error write_result_;
239 
240     DISALLOW_COPY_AND_ASSIGN(TestCopyOrMoveFileValidator);
241   };
242 
243   Validity validity_;
244 
245   DISALLOW_COPY_AND_ASSIGN(TestCopyOrMoveFileValidatorFactory);
246 };
247 
248 }  // namespace
249 
TEST(CopyOrMoveFileValidatorTest,NoValidatorWithinSameFSType)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"),
254                                            kWithValidatorType,
255                                            kWithValidatorType);
256   helper.SetUp();
257   helper.CopyTest(base::File::FILE_OK);
258   helper.MoveTest(base::File::FILE_OK);
259 }
260 
TEST(CopyOrMoveFileValidatorTest,MissingValidator)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"),
265                                            kNoValidatorType,
266                                            kWithValidatorType);
267   helper.SetUp();
268   helper.CopyTest(base::File::FILE_ERROR_SECURITY);
269   helper.MoveTest(base::File::FILE_ERROR_SECURITY);
270 }
271 
TEST(CopyOrMoveFileValidatorTest,AcceptAll)272 TEST(CopyOrMoveFileValidatorTest, AcceptAll) {
273   CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
274                                            kNoValidatorType,
275                                            kWithValidatorType);
276   helper.SetUp();
277   scoped_ptr<CopyOrMoveFileValidatorFactory> factory(
278       new TestCopyOrMoveFileValidatorFactory(VALID));
279   helper.SetMediaCopyOrMoveFileValidatorFactory(factory.Pass());
280 
281   helper.CopyTest(base::File::FILE_OK);
282   helper.MoveTest(base::File::FILE_OK);
283 }
284 
TEST(CopyOrMoveFileValidatorTest,AcceptNone)285 TEST(CopyOrMoveFileValidatorTest, AcceptNone) {
286   CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
287                                            kNoValidatorType,
288                                            kWithValidatorType);
289   helper.SetUp();
290   scoped_ptr<CopyOrMoveFileValidatorFactory> factory(
291       new TestCopyOrMoveFileValidatorFactory(PRE_WRITE_INVALID));
292   helper.SetMediaCopyOrMoveFileValidatorFactory(factory.Pass());
293 
294   helper.CopyTest(base::File::FILE_ERROR_SECURITY);
295   helper.MoveTest(base::File::FILE_ERROR_SECURITY);
296 }
297 
TEST(CopyOrMoveFileValidatorTest,OverrideValidator)298 TEST(CopyOrMoveFileValidatorTest, OverrideValidator) {
299   // Once set, you can not override the validator.
300   CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
301                                            kNoValidatorType,
302                                            kWithValidatorType);
303   helper.SetUp();
304   scoped_ptr<CopyOrMoveFileValidatorFactory> reject_factory(
305       new TestCopyOrMoveFileValidatorFactory(PRE_WRITE_INVALID));
306   helper.SetMediaCopyOrMoveFileValidatorFactory(reject_factory.Pass());
307 
308   scoped_ptr<CopyOrMoveFileValidatorFactory> accept_factory(
309       new TestCopyOrMoveFileValidatorFactory(VALID));
310   helper.SetMediaCopyOrMoveFileValidatorFactory(accept_factory.Pass());
311 
312   helper.CopyTest(base::File::FILE_ERROR_SECURITY);
313   helper.MoveTest(base::File::FILE_ERROR_SECURITY);
314 }
315 
TEST(CopyOrMoveFileValidatorTest,RejectPostWrite)316 TEST(CopyOrMoveFileValidatorTest, RejectPostWrite) {
317   CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
318                                            kNoValidatorType,
319                                            kWithValidatorType);
320   helper.SetUp();
321   scoped_ptr<CopyOrMoveFileValidatorFactory> factory(
322       new TestCopyOrMoveFileValidatorFactory(POST_WRITE_INVALID));
323   helper.SetMediaCopyOrMoveFileValidatorFactory(factory.Pass());
324 
325   helper.CopyTest(base::File::FILE_ERROR_SECURITY);
326   helper.MoveTest(base::File::FILE_ERROR_SECURITY);
327 }
328 
329 }  // namespace content
330