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/file_util.h"
      9 #include "base/files/scoped_temp_dir.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "base/message_loop/message_loop_proxy.h"
     12 #include "base/path_service.h"
     13 #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
     14 #include "chrome/test/base/in_process_browser_test.h"
     15 #include "content/public/test/browser_test.h"
     16 #include "content/public/test/test_file_system_backend.h"
     17 #include "content/public/test/test_file_system_context.h"
     18 #include "content/public/test/test_utils.h"
     19 #include "storage/browser/fileapi/copy_or_move_file_validator.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_operation_runner.h"
     23 #include "storage/browser/fileapi/file_system_url.h"
     24 #include "storage/browser/fileapi/isolated_context.h"
     25 #include "storage/common/fileapi/file_system_types.h"
     26 #include "testing/gtest/include/gtest/gtest.h"
     27 
     28 namespace {
     29 
     30 const char kOrigin[] = "http://foo";
     31 
     32 const char kValidImage[] = "RIFF0\0\0\0WEBPVP8 $\0\0\0\xB2\x02\0\x9D\x01\x2A"
     33                            "\x01\0\x01\0\x2F\x9D\xCE\xE7s\xA8((((\x01\x9CK(\0"
     34                            "\x05\xCE\xB3l\0\0\xFE\xD8\x80\0\0";
     35 
     36 const char kInvalidMediaFile[] = "Not a media file";
     37 
     38 const int64 kNoFileSize = -1;
     39 
     40 void HandleCheckFileResult(int64 expected_size,
     41                            const base::Callback<void(bool success)>& callback,
     42                            base::File::Error result,
     43                            const base::File::Info& file_info) {
     44   if (result == base::File::FILE_OK) {
     45     if (!file_info.is_directory && expected_size != kNoFileSize &&
     46         file_info.size == expected_size) {
     47       callback.Run(true);
     48       return;
     49     }
     50   } else {
     51     if (expected_size == kNoFileSize) {
     52       callback.Run(true);
     53       return;
     54     }
     55   }
     56   callback.Run(false);
     57 }
     58 
     59 base::FilePath GetMediaTestDir() {
     60   base::FilePath test_file;
     61   if (!PathService::Get(base::DIR_SOURCE_ROOT, &test_file))
     62     return base::FilePath();
     63   return test_file.AppendASCII("media").AppendASCII("test").AppendASCII("data");
     64 }
     65 
     66 }  // namespace
     67 
     68 class MediaFileValidatorTest : public InProcessBrowserTest {
     69  public:
     70   MediaFileValidatorTest() : test_file_size_(0) {}
     71 
     72   virtual ~MediaFileValidatorTest() {}
     73 
     74   // Write |content| into |filename| in a test file system and try to move
     75   // it into a media file system.  The result is compared to |expected_result|.
     76   void MoveTest(const std::string& filename, const std::string& content,
     77                 bool expected_result) {
     78     content::BrowserThread::PostTask(
     79         content::BrowserThread::FILE,
     80         FROM_HERE,
     81         base::Bind(&MediaFileValidatorTest::SetupOnFileThread,
     82                    base::Unretained(this), filename, content, expected_result));
     83     loop_runner_ = new content::MessageLoopRunner;
     84     loop_runner_->Run();
     85   }
     86 
     87   // Write |source| into |filename| in a test file system and try to move it
     88   // into a media file system.  The result is compared to |expected_result|.
     89   void MoveTestFromFile(const std::string& filename,
     90                         const base::FilePath& source, bool expected_result) {
     91     content::BrowserThread::PostTask(
     92         content::BrowserThread::FILE,
     93         FROM_HERE,
     94         base::Bind(&MediaFileValidatorTest::SetupFromFileOnFileThread,
     95                    base::Unretained(this), filename, source, expected_result));
     96     loop_runner_ = new content::MessageLoopRunner;
     97     loop_runner_->Run();
     98   }
     99 
    100  private:
    101   // Create the test files, filesystem objects, etc.
    102   void SetupOnFileThread(const std::string& filename,
    103                          const std::string& content,
    104                          bool expected_result) {
    105     ASSERT_TRUE(base_dir_.CreateUniqueTempDir());
    106     base::FilePath base = base_dir_.path();
    107     base::FilePath src_path = base.AppendASCII("src_fs");
    108     ASSERT_TRUE(base::CreateDirectory(src_path));
    109 
    110     ScopedVector<storage::FileSystemBackend> additional_providers;
    111     additional_providers.push_back(new content::TestFileSystemBackend(
    112         base::MessageLoopProxy::current().get(), src_path));
    113     additional_providers.push_back(new MediaFileSystemBackend(
    114         base, base::MessageLoopProxy::current().get()));
    115     file_system_context_ =
    116         content::CreateFileSystemContextWithAdditionalProvidersForTesting(
    117             NULL, additional_providers.Pass(), base);
    118 
    119     move_src_ = file_system_context_->CreateCrackedFileSystemURL(
    120         GURL(kOrigin),
    121         storage::kFileSystemTypeTest,
    122         base::FilePath::FromUTF8Unsafe(filename));
    123 
    124     test_file_size_ = content.size();
    125     base::FilePath test_file = src_path.AppendASCII(filename);
    126     ASSERT_EQ(test_file_size_,
    127               base::WriteFile(test_file, content.data(), test_file_size_));
    128 
    129     base::FilePath dest_path = base.AppendASCII("dest_fs");
    130     ASSERT_TRUE(base::CreateDirectory(dest_path));
    131     std::string dest_fsid =
    132         storage::IsolatedContext::GetInstance()->RegisterFileSystemForPath(
    133             storage::kFileSystemTypeNativeMedia,
    134             std::string(),
    135             dest_path,
    136             NULL);
    137 
    138     size_t extension_index = filename.find_last_of(".");
    139     ASSERT_NE(std::string::npos, extension_index);
    140     std::string extension = filename.substr(extension_index);
    141     std::string dest_root_fs_url = storage::GetIsolatedFileSystemRootURIString(
    142         GURL(kOrigin), dest_fsid, "dest_fs/");
    143     move_dest_ = file_system_context_->CrackURL(GURL(
    144           dest_root_fs_url + "move_dest" + extension));
    145 
    146     content::BrowserThread::PostTask(
    147         content::BrowserThread::IO,
    148         FROM_HERE,
    149         base::Bind(&MediaFileValidatorTest::CheckFiles,
    150                    base::Unretained(this), true,
    151                    base::Bind(&MediaFileValidatorTest::OnTestFilesReady,
    152                               base::Unretained(this), expected_result)));
    153   }
    154 
    155   void SetupFromFileOnFileThread(const std::string& filename,
    156                                  const base::FilePath& source,
    157                                  bool expected_result) {
    158     std::string content;
    159     ASSERT_TRUE(base::ReadFileToString(source, &content));
    160     SetupOnFileThread(filename, content, expected_result);
    161   }
    162 
    163   // Check that exactly one of |move_src_| and |move_dest_| exists.
    164   // |src_expected| indicates which one should exist.  When complete,
    165   // |callback| is called with success/failure.
    166   void CheckFiles(bool src_expected,
    167                   const base::Callback<void(bool success)>& callback) {
    168     CheckFile(move_src_, src_expected ? test_file_size_ : kNoFileSize,
    169               base::Bind(&MediaFileValidatorTest::OnCheckFilesFirstResult,
    170                          base::Unretained(this), !src_expected, callback));
    171   }
    172 
    173   // Helper that checks a file has the |expected_size|, which may be
    174   // |kNoFileSize| if the file should not exist.  |callback| is called
    175   // with success/failure.
    176   void CheckFile(storage::FileSystemURL url,
    177                  int64 expected_size,
    178                  const base::Callback<void(bool success)>& callback) {
    179     operation_runner()->GetMetadata(url,
    180                                     base::Bind(&HandleCheckFileResult,
    181                                                expected_size, callback));
    182   }
    183 
    184   // Helper that checks the result of |move_src_| lookup and then checks
    185   // |move_dest_| if all is as expected.
    186   void OnCheckFilesFirstResult(bool dest_expected,
    187                                const base::Callback<void(bool)>& callback,
    188                                bool src_result) {
    189     EXPECT_TRUE(src_result);
    190     if (!src_result) {
    191       callback.Run(false);
    192       return;
    193     }
    194     CheckFile(move_dest_, dest_expected ? test_file_size_ : kNoFileSize,
    195               callback);
    196   }
    197 
    198   // Assert |test_files_ready| and then do the actual test of moving
    199   // |move_src_| to |move_dest_|.
    200   void OnTestFilesReady(bool expected_result, bool test_files_ready) {
    201     ASSERT_TRUE(test_files_ready);
    202     operation_runner()->Move(move_src_,
    203                              move_dest_,
    204                              storage::FileSystemOperation::OPTION_NONE,
    205                              base::Bind(&MediaFileValidatorTest::OnMoveResult,
    206                                         base::Unretained(this),
    207                                         expected_result));
    208   }
    209 
    210   // Check that the move succeeded/failed based on expectation and then
    211   // check that the right file exists.
    212   void OnMoveResult(bool expected_result, base::File::Error result) {
    213     if (expected_result)
    214       EXPECT_EQ(base::File::FILE_OK, result);
    215     else
    216       EXPECT_EQ(base::File::FILE_ERROR_SECURITY, result);
    217     CheckFiles(!expected_result,
    218                base::Bind(&MediaFileValidatorTest::OnTestFilesCheckResult,
    219                           base::Unretained(this)));
    220   }
    221 
    222   // Check that the correct test file exists and then post the result back
    223   // to the UI thread.
    224   void OnTestFilesCheckResult(bool result) {
    225     EXPECT_TRUE(result);
    226     content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
    227                                      loop_runner_->QuitClosure());
    228   }
    229 
    230   storage::FileSystemOperationRunner* operation_runner() {
    231     return file_system_context_->operation_runner();
    232   }
    233 
    234   base::ScopedTempDir base_dir_;
    235 
    236   scoped_refptr<storage::FileSystemContext> file_system_context_;
    237 
    238   int test_file_size_;
    239 
    240   storage::FileSystemURL move_src_;
    241   storage::FileSystemURL move_dest_;
    242 
    243   scoped_refptr<content::MessageLoopRunner> loop_runner_;
    244 
    245   DISALLOW_COPY_AND_ASSIGN(MediaFileValidatorTest);
    246 };
    247 
    248 IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, UnsupportedExtension) {
    249   MoveTest("a.txt", std::string(kValidImage, arraysize(kValidImage)), false);
    250 }
    251 
    252 IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, ValidImage) {
    253   MoveTest("a.webp", std::string(kValidImage, arraysize(kValidImage)), true);
    254 }
    255 
    256 IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, InvalidImage) {
    257   MoveTest("a.webp", std::string(kInvalidMediaFile,
    258            arraysize(kInvalidMediaFile)), false);
    259 }
    260 
    261 IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, InvalidAudio) {
    262   MoveTest("a.ogg", std::string(kInvalidMediaFile,
    263            arraysize(kInvalidMediaFile)), false);
    264 }
    265 
    266 IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, ValidAudio) {
    267   base::FilePath test_file = GetMediaTestDir();
    268   ASSERT_FALSE(test_file.empty());
    269   test_file = test_file.AppendASCII("sfx.ogg");
    270   MoveTestFromFile("sfx.ogg", test_file, true);
    271 }
    272 
    273 IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, InvalidVideo) {
    274   base::FilePath test_file = GetMediaTestDir();
    275   ASSERT_FALSE(test_file.empty());
    276   test_file = test_file.AppendASCII("no_streams.webm");
    277   MoveTestFromFile("no_streams.webm", test_file, false);
    278 }
    279 
    280 IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, ValidVideo) {
    281   base::FilePath test_file = GetMediaTestDir();
    282   ASSERT_FALSE(test_file.empty());
    283   test_file = test_file.AppendASCII("bear-320x240-multitrack.webm");
    284   MoveTestFromFile("multitrack.webm", test_file, true);
    285 }
    286