Home | History | Annotate | Download | only in fileapi
      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/message_loop/message_loop.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 #include "webkit/browser/fileapi/async_file_test_helper.h"
     12 #include "webkit/browser/fileapi/copy_or_move_file_validator.h"
     13 #include "webkit/browser/fileapi/external_mount_points.h"
     14 #include "webkit/browser/fileapi/file_system_backend.h"
     15 #include "webkit/browser/fileapi/file_system_context.h"
     16 #include "webkit/browser/fileapi/file_system_url.h"
     17 #include "webkit/browser/fileapi/isolated_context.h"
     18 #include "webkit/browser/fileapi/mock_file_system_context.h"
     19 #include "webkit/browser/fileapi/test_file_system_backend.h"
     20 #include "webkit/browser/quota/mock_special_storage_policy.h"
     21 #include "webkit/common/blob/shareable_file_reference.h"
     22 #include "webkit/common/fileapi/file_system_util.h"
     23 
     24 namespace fileapi {
     25 
     26 namespace {
     27 
     28 const FileSystemType kNoValidatorType = kFileSystemTypeTemporary;
     29 const FileSystemType kWithValidatorType = kFileSystemTypeTest;
     30 
     31 void ExpectOk(const GURL& origin_url,
     32               const std::string& name,
     33               base::PlatformFileError error) {
     34   ASSERT_EQ(base::PLATFORM_FILE_OK, error);
     35 }
     36 
     37 class CopyOrMoveFileValidatorTestHelper {
     38  public:
     39   CopyOrMoveFileValidatorTestHelper(
     40       const GURL& origin,
     41       FileSystemType src_type,
     42       FileSystemType dest_type)
     43       : origin_(origin),
     44         src_type_(src_type),
     45         dest_type_(dest_type) {}
     46 
     47   ~CopyOrMoveFileValidatorTestHelper() {
     48     file_system_context_ = NULL;
     49     base::MessageLoop::current()->RunUntilIdle();
     50   }
     51 
     52   void SetUp() {
     53     ASSERT_TRUE(base_.CreateUniqueTempDir());
     54     base::FilePath base_dir = base_.path();
     55 
     56     file_system_context_ = CreateFileSystemContextForTesting(NULL, base_dir);
     57 
     58     // Set up TestFileSystemBackend to require CopyOrMoveFileValidator.
     59     FileSystemBackend* test_file_system_backend =
     60         file_system_context_->GetFileSystemBackend(kWithValidatorType);
     61     static_cast<TestFileSystemBackend*>(test_file_system_backend)->
     62         set_require_copy_or_move_validator(true);
     63 
     64     // Sets up source.
     65     FileSystemBackend* src_file_system_backend =
     66         file_system_context_->GetFileSystemBackend(src_type_);
     67     src_file_system_backend->OpenFileSystem(
     68         origin_, src_type_,
     69         OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
     70         base::Bind(&ExpectOk));
     71     base::MessageLoop::current()->RunUntilIdle();
     72     ASSERT_EQ(base::PLATFORM_FILE_OK, CreateDirectory(SourceURL("")));
     73 
     74     // Sets up dest.
     75     DCHECK_EQ(kWithValidatorType, dest_type_);
     76     ASSERT_EQ(base::PLATFORM_FILE_OK, CreateDirectory(DestURL("")));
     77 
     78     copy_src_ = SourceURL("copy_src.jpg");
     79     move_src_ = SourceURL("move_src.jpg");
     80     copy_dest_ = DestURL("copy_dest.jpg");
     81     move_dest_ = DestURL("move_dest.jpg");
     82 
     83     ASSERT_EQ(base::PLATFORM_FILE_OK, CreateFile(copy_src_, 10));
     84     ASSERT_EQ(base::PLATFORM_FILE_OK, CreateFile(move_src_, 10));
     85 
     86     ASSERT_TRUE(FileExists(copy_src_, 10));
     87     ASSERT_TRUE(FileExists(move_src_, 10));
     88     ASSERT_FALSE(FileExists(copy_dest_, 10));
     89     ASSERT_FALSE(FileExists(move_dest_, 10));
     90   }
     91 
     92   void SetMediaCopyOrMoveFileValidatorFactory(
     93       scoped_ptr<CopyOrMoveFileValidatorFactory> factory) {
     94     TestFileSystemBackend* backend = static_cast<TestFileSystemBackend*>(
     95         file_system_context_->GetFileSystemBackend(kWithValidatorType));
     96     backend->InitializeCopyOrMoveFileValidatorFactory(factory.Pass());
     97   }
     98 
     99   void CopyTest(base::PlatformFileError expected) {
    100     ASSERT_TRUE(FileExists(copy_src_, 10));
    101     ASSERT_FALSE(FileExists(copy_dest_, 10));
    102 
    103     EXPECT_EQ(expected,
    104               AsyncFileTestHelper::Copy(
    105                   file_system_context_.get(), copy_src_, copy_dest_));
    106 
    107     EXPECT_TRUE(FileExists(copy_src_, 10));
    108     if (expected == base::PLATFORM_FILE_OK)
    109       EXPECT_TRUE(FileExists(copy_dest_, 10));
    110     else
    111       EXPECT_FALSE(FileExists(copy_dest_, 10));
    112   };
    113 
    114   void MoveTest(base::PlatformFileError expected) {
    115     ASSERT_TRUE(FileExists(move_src_, 10));
    116     ASSERT_FALSE(FileExists(move_dest_, 10));
    117 
    118     EXPECT_EQ(expected,
    119               AsyncFileTestHelper::Move(
    120                   file_system_context_.get(), move_src_, move_dest_));
    121 
    122     if (expected == base::PLATFORM_FILE_OK) {
    123       EXPECT_FALSE(FileExists(move_src_, 10));
    124       EXPECT_TRUE(FileExists(move_dest_, 10));
    125     } else {
    126       EXPECT_TRUE(FileExists(move_src_, 10));
    127       EXPECT_FALSE(FileExists(move_dest_, 10));
    128     }
    129   };
    130 
    131  private:
    132   FileSystemURL SourceURL(const std::string& path) {
    133     return file_system_context_->CreateCrackedFileSystemURL(
    134         origin_, src_type_,
    135         base::FilePath().AppendASCII("src").AppendASCII(path));
    136   }
    137 
    138   FileSystemURL DestURL(const std::string& path) {
    139     return file_system_context_->CreateCrackedFileSystemURL(
    140         origin_, dest_type_,
    141         base::FilePath().AppendASCII("dest").AppendASCII(path));
    142   }
    143 
    144   base::PlatformFileError CreateFile(const FileSystemURL& url, size_t size) {
    145     base::PlatformFileError result =
    146         AsyncFileTestHelper::CreateFile(file_system_context_.get(), url);
    147     if (result != base::PLATFORM_FILE_OK)
    148       return result;
    149     return AsyncFileTestHelper::TruncateFile(
    150         file_system_context_.get(), url, size);
    151   }
    152 
    153   base::PlatformFileError CreateDirectory(const FileSystemURL& url) {
    154     return AsyncFileTestHelper::CreateDirectory(file_system_context_.get(),
    155                                                 url);
    156   }
    157 
    158   bool FileExists(const FileSystemURL& url, int64 expected_size) {
    159     return AsyncFileTestHelper::FileExists(
    160         file_system_context_.get(), url, expected_size);
    161   }
    162 
    163   base::ScopedTempDir base_;
    164 
    165   const GURL origin_;
    166 
    167   const FileSystemType src_type_;
    168   const FileSystemType dest_type_;
    169   std::string src_fsid_;
    170   std::string dest_fsid_;
    171 
    172   base::MessageLoop message_loop_;
    173   scoped_refptr<FileSystemContext> file_system_context_;
    174 
    175   FileSystemURL copy_src_;
    176   FileSystemURL copy_dest_;
    177   FileSystemURL move_src_;
    178   FileSystemURL move_dest_;
    179 
    180   DISALLOW_COPY_AND_ASSIGN(CopyOrMoveFileValidatorTestHelper);
    181 };
    182 
    183 // For TestCopyOrMoveFileValidatorFactory
    184 enum Validity {
    185   VALID,
    186   PRE_WRITE_INVALID,
    187   POST_WRITE_INVALID
    188 };
    189 
    190 class TestCopyOrMoveFileValidatorFactory
    191     : public CopyOrMoveFileValidatorFactory {
    192  public:
    193   // A factory that creates validators that accept everything or nothing.
    194   // TODO(gbillock): switch args to enum or something
    195   explicit TestCopyOrMoveFileValidatorFactory(Validity validity)
    196       : validity_(validity) {}
    197   virtual ~TestCopyOrMoveFileValidatorFactory() {}
    198 
    199   virtual CopyOrMoveFileValidator* CreateCopyOrMoveFileValidator(
    200       const FileSystemURL& /*src_url*/,
    201       const base::FilePath& /*platform_path*/) OVERRIDE {
    202     return new TestCopyOrMoveFileValidator(validity_);
    203   }
    204 
    205  private:
    206   class TestCopyOrMoveFileValidator : public CopyOrMoveFileValidator {
    207    public:
    208     explicit TestCopyOrMoveFileValidator(Validity validity)
    209         : result_(validity == VALID || validity == POST_WRITE_INVALID
    210                   ? base::PLATFORM_FILE_OK
    211                   : base::PLATFORM_FILE_ERROR_SECURITY),
    212           write_result_(validity == VALID || validity == PRE_WRITE_INVALID
    213                         ? base::PLATFORM_FILE_OK
    214                         : base::PLATFORM_FILE_ERROR_SECURITY) {
    215     }
    216     virtual ~TestCopyOrMoveFileValidator() {}
    217 
    218     virtual void StartPreWriteValidation(
    219         const ResultCallback& result_callback) OVERRIDE {
    220       // Post the result since a real validator must do work asynchronously.
    221       base::MessageLoop::current()->PostTask(
    222           FROM_HERE, base::Bind(result_callback, result_));
    223     }
    224 
    225     virtual void StartPostWriteValidation(
    226         const base::FilePath& dest_platform_path,
    227         const ResultCallback& result_callback) OVERRIDE {
    228       // Post the result since a real validator must do work asynchronously.
    229       base::MessageLoop::current()->PostTask(
    230           FROM_HERE, base::Bind(result_callback, write_result_));
    231     }
    232 
    233    private:
    234     base::PlatformFileError result_;
    235     base::PlatformFileError write_result_;
    236 
    237     DISALLOW_COPY_AND_ASSIGN(TestCopyOrMoveFileValidator);
    238   };
    239 
    240   Validity validity_;
    241 
    242   DISALLOW_COPY_AND_ASSIGN(TestCopyOrMoveFileValidatorFactory);
    243 };
    244 
    245 }  // namespace
    246 
    247 TEST(CopyOrMoveFileValidatorTest, NoValidatorWithinSameFSType) {
    248   // Within a file system type, validation is not expected, so it should
    249   // work for kWithValidatorType without a validator set.
    250   CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
    251                                            kWithValidatorType,
    252                                            kWithValidatorType);
    253   helper.SetUp();
    254   helper.CopyTest(base::PLATFORM_FILE_OK);
    255   helper.MoveTest(base::PLATFORM_FILE_OK);
    256 }
    257 
    258 TEST(CopyOrMoveFileValidatorTest, MissingValidator) {
    259   // Copying or moving into a kWithValidatorType requires a file
    260   // validator.  An error is expected if copy is attempted without a validator.
    261   CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
    262                                            kNoValidatorType,
    263                                            kWithValidatorType);
    264   helper.SetUp();
    265   helper.CopyTest(base::PLATFORM_FILE_ERROR_SECURITY);
    266   helper.MoveTest(base::PLATFORM_FILE_ERROR_SECURITY);
    267 }
    268 
    269 TEST(CopyOrMoveFileValidatorTest, AcceptAll) {
    270   CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
    271                                            kNoValidatorType,
    272                                            kWithValidatorType);
    273   helper.SetUp();
    274   scoped_ptr<CopyOrMoveFileValidatorFactory> factory(
    275       new TestCopyOrMoveFileValidatorFactory(VALID));
    276   helper.SetMediaCopyOrMoveFileValidatorFactory(factory.Pass());
    277 
    278   helper.CopyTest(base::PLATFORM_FILE_OK);
    279   helper.MoveTest(base::PLATFORM_FILE_OK);
    280 }
    281 
    282 TEST(CopyOrMoveFileValidatorTest, AcceptNone) {
    283   CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
    284                                            kNoValidatorType,
    285                                            kWithValidatorType);
    286   helper.SetUp();
    287   scoped_ptr<CopyOrMoveFileValidatorFactory> factory(
    288       new TestCopyOrMoveFileValidatorFactory(PRE_WRITE_INVALID));
    289   helper.SetMediaCopyOrMoveFileValidatorFactory(factory.Pass());
    290 
    291   helper.CopyTest(base::PLATFORM_FILE_ERROR_SECURITY);
    292   helper.MoveTest(base::PLATFORM_FILE_ERROR_SECURITY);
    293 }
    294 
    295 TEST(CopyOrMoveFileValidatorTest, OverrideValidator) {
    296   // Once set, you can not override the validator.
    297   CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
    298                                            kNoValidatorType,
    299                                            kWithValidatorType);
    300   helper.SetUp();
    301   scoped_ptr<CopyOrMoveFileValidatorFactory> reject_factory(
    302       new TestCopyOrMoveFileValidatorFactory(PRE_WRITE_INVALID));
    303   helper.SetMediaCopyOrMoveFileValidatorFactory(reject_factory.Pass());
    304 
    305   scoped_ptr<CopyOrMoveFileValidatorFactory> accept_factory(
    306       new TestCopyOrMoveFileValidatorFactory(VALID));
    307   helper.SetMediaCopyOrMoveFileValidatorFactory(accept_factory.Pass());
    308 
    309   helper.CopyTest(base::PLATFORM_FILE_ERROR_SECURITY);
    310   helper.MoveTest(base::PLATFORM_FILE_ERROR_SECURITY);
    311 }
    312 
    313 TEST(CopyOrMoveFileValidatorTest, RejectPostWrite) {
    314   CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
    315                                            kNoValidatorType,
    316                                            kWithValidatorType);
    317   helper.SetUp();
    318   scoped_ptr<CopyOrMoveFileValidatorFactory> factory(
    319       new TestCopyOrMoveFileValidatorFactory(POST_WRITE_INVALID));
    320   helper.SetMediaCopyOrMoveFileValidatorFactory(factory.Pass());
    321 
    322   helper.CopyTest(base::PLATFORM_FILE_ERROR_SECURITY);
    323   helper.MoveTest(base::PLATFORM_FILE_ERROR_SECURITY);
    324 }
    325 
    326 }  // namespace fileapi
    327