media_file_validator_browsertest.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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/file_util.h" 8#include "base/files/file_path.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 "testing/gtest/include/gtest/gtest.h" 20#include "webkit/browser/fileapi/copy_or_move_file_validator.h" 21#include "webkit/browser/fileapi/file_system_backend.h" 22#include "webkit/browser/fileapi/file_system_context.h" 23#include "webkit/browser/fileapi/file_system_operation_runner.h" 24#include "webkit/browser/fileapi/file_system_url.h" 25#include "webkit/browser/fileapi/isolated_context.h" 26#include "webkit/common/fileapi/file_system_types.h" 27 28namespace { 29 30const char kOrigin[] = "http://foo"; 31 32const 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 36const char kInvalidMediaFile[] = "Not a media file"; 37 38const int64 kNoFileSize = -1; 39 40void HandleCheckFileResult(int64 expected_size, 41 const base::Callback<void(bool success)>& callback, 42 base::PlatformFileError result, 43 const base::PlatformFileInfo& file_info) { 44 if (result == base::PLATFORM_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 59base::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 68class 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(file_util::CreateDirectory(src_path)); 109 110 ScopedVector<fileapi::FileSystemBackend> additional_providers; 111 additional_providers.push_back(new fileapi::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 fileapi::CreateFileSystemContextWithAdditionalProvidersForTesting( 117 NULL, additional_providers.Pass(), base); 118 119 move_src_ = file_system_context_->CreateCrackedFileSystemURL( 120 GURL(kOrigin), fileapi::kFileSystemTypeTest, 121 base::FilePath::FromUTF8Unsafe(filename)); 122 123 test_file_size_ = content.size(); 124 base::FilePath test_file = src_path.AppendASCII(filename); 125 ASSERT_EQ(test_file_size_, 126 file_util::WriteFile(test_file, content.data(), test_file_size_)); 127 128 base::FilePath dest_path = base.AppendASCII("dest_fs"); 129 ASSERT_TRUE(file_util::CreateDirectory(dest_path)); 130 std::string dest_fsid = 131 fileapi::IsolatedContext::GetInstance()->RegisterFileSystemForPath( 132 fileapi::kFileSystemTypeNativeMedia, dest_path, NULL); 133 134 size_t extension_index = filename.find_last_of("."); 135 ASSERT_NE(std::string::npos, extension_index); 136 std::string extension = filename.substr(extension_index); 137 std::string dest_root_fs_url = fileapi::GetIsolatedFileSystemRootURIString( 138 GURL(kOrigin), dest_fsid, "dest_fs/"); 139 move_dest_ = file_system_context_->CrackURL(GURL( 140 dest_root_fs_url + "move_dest" + extension)); 141 142 content::BrowserThread::PostTask( 143 content::BrowserThread::IO, 144 FROM_HERE, 145 base::Bind(&MediaFileValidatorTest::CheckFiles, 146 base::Unretained(this), true, 147 base::Bind(&MediaFileValidatorTest::OnTestFilesReady, 148 base::Unretained(this), expected_result))); 149 } 150 151 void SetupFromFileOnFileThread(const std::string& filename, 152 const base::FilePath& source, 153 bool expected_result) { 154 std::string content; 155 ASSERT_TRUE(base::ReadFileToString(source, &content)); 156 SetupOnFileThread(filename, content, expected_result); 157 } 158 159 // Check that exactly one of |move_src_| and |move_dest_| exists. 160 // |src_expected| indicates which one should exist. When complete, 161 // |callback| is called with success/failure. 162 void CheckFiles(bool src_expected, 163 const base::Callback<void(bool success)>& callback) { 164 CheckFile(move_src_, src_expected ? test_file_size_ : kNoFileSize, 165 base::Bind(&MediaFileValidatorTest::OnCheckFilesFirstResult, 166 base::Unretained(this), !src_expected, callback)); 167 } 168 169 // Helper that checks a file has the |expected_size|, which may be 170 // |kNoFileSize| if the file should not exist. |callback| is called 171 // with success/failure. 172 void CheckFile(fileapi::FileSystemURL url, 173 int64 expected_size, 174 const base::Callback<void(bool success)>& callback) { 175 operation_runner()->GetMetadata(url, 176 base::Bind(&HandleCheckFileResult, 177 expected_size, callback)); 178 } 179 180 // Helper that checks the result of |move_src_| lookup and then checks 181 // |move_dest_| if all is as expected. 182 void OnCheckFilesFirstResult(bool dest_expected, 183 const base::Callback<void(bool)>& callback, 184 bool src_result) { 185 EXPECT_TRUE(src_result); 186 if (!src_result) { 187 callback.Run(false); 188 return; 189 } 190 CheckFile(move_dest_, dest_expected ? test_file_size_ : kNoFileSize, 191 callback); 192 } 193 194 // Assert |test_files_ready| and then do the actual test of moving 195 // |move_src_| to |move_dest_|. 196 void OnTestFilesReady(bool expected_result, bool test_files_ready) { 197 ASSERT_TRUE(test_files_ready); 198 operation_runner()->Move( 199 move_src_, move_dest_, fileapi::FileSystemOperation::OPTION_NONE, 200 base::Bind(&MediaFileValidatorTest::OnMoveResult, 201 base::Unretained(this), expected_result)); 202 } 203 204 // Check that the move succeeded/failed based on expectation and then 205 // check that the right file exists. 206 void OnMoveResult(bool expected_result, base::PlatformFileError result) { 207 if (expected_result) 208 EXPECT_EQ(base::PLATFORM_FILE_OK, result); 209 else 210 EXPECT_EQ(base::PLATFORM_FILE_ERROR_SECURITY, result); 211 CheckFiles(!expected_result, 212 base::Bind(&MediaFileValidatorTest::OnTestFilesCheckResult, 213 base::Unretained(this))); 214 } 215 216 // Check that the correct test file exists and then post the result back 217 // to the UI thread. 218 void OnTestFilesCheckResult(bool result) { 219 EXPECT_TRUE(result); 220 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 221 loop_runner_->QuitClosure()); 222 } 223 224 fileapi::FileSystemOperationRunner* operation_runner() { 225 return file_system_context_->operation_runner(); 226 } 227 228 base::ScopedTempDir base_dir_; 229 230 scoped_refptr<fileapi::FileSystemContext> file_system_context_; 231 232 int test_file_size_; 233 234 fileapi::FileSystemURL move_src_; 235 fileapi::FileSystemURL move_dest_; 236 237 scoped_refptr<content::MessageLoopRunner> loop_runner_; 238 239 DISALLOW_COPY_AND_ASSIGN(MediaFileValidatorTest); 240}; 241 242IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, UnsupportedExtension) { 243 MoveTest("a.txt", std::string(kValidImage, arraysize(kValidImage)), false); 244} 245 246IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, ValidImage) { 247 MoveTest("a.webp", std::string(kValidImage, arraysize(kValidImage)), true); 248} 249 250IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, InvalidImage) { 251 MoveTest("a.webp", std::string(kInvalidMediaFile, 252 arraysize(kInvalidMediaFile)), false); 253} 254 255IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, InvalidAudio) { 256 MoveTest("a.ogg", std::string(kInvalidMediaFile, 257 arraysize(kInvalidMediaFile)), false); 258} 259 260IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, ValidAudio) { 261 base::FilePath test_file = GetMediaTestDir(); 262 ASSERT_FALSE(test_file.empty()); 263 test_file = test_file.AppendASCII("sfx.ogg"); 264 MoveTestFromFile("sfx.ogg", test_file, true); 265} 266 267IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, InvalidVideo) { 268 base::FilePath test_file = GetMediaTestDir(); 269 ASSERT_FALSE(test_file.empty()); 270 test_file = test_file.AppendASCII("no_streams.webm"); 271 MoveTestFromFile("no_streams.webm", test_file, false); 272} 273 274IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, ValidVideo) { 275 base::FilePath test_file = GetMediaTestDir(); 276 ASSERT_FALSE(test_file.empty()); 277 test_file = test_file.AppendASCII("bear-320x240-multitrack.webm"); 278 MoveTestFromFile("multitrack.webm", test_file, true); 279} 280