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 "storage/browser/fileapi/sandbox_file_system_backend.h" 6 7#include <set> 8 9#include "base/basictypes.h" 10#include "base/files/file_util.h" 11#include "base/files/scoped_temp_dir.h" 12#include "base/memory/scoped_ptr.h" 13#include "base/message_loop/message_loop_proxy.h" 14#include "base/run_loop.h" 15#include "content/public/test/test_file_system_options.h" 16#include "storage/browser/fileapi/file_system_backend.h" 17#include "storage/browser/fileapi/file_system_url.h" 18#include "storage/browser/fileapi/sandbox_file_system_backend_delegate.h" 19#include "storage/common/fileapi/file_system_util.h" 20#include "testing/gtest/include/gtest/gtest.h" 21#include "url/gurl.h" 22 23using storage::FileSystemURL; 24using storage::SandboxFileSystemBackend; 25using storage::SandboxFileSystemBackendDelegate; 26 27// PS stands for path separator. 28#if defined(FILE_PATH_USES_WIN_SEPARATORS) 29#define PS "\\" 30#else 31#define PS "/" 32#endif 33 34namespace content { 35 36namespace { 37 38const struct RootPathTest { 39 storage::FileSystemType type; 40 const char* origin_url; 41 const char* expected_path; 42} kRootPathTestCases[] = { 43 {storage::kFileSystemTypeTemporary, "http://foo:1/", "000" PS "t"}, 44 {storage::kFileSystemTypePersistent, "http://foo:1/", "000" PS "p"}, 45 {storage::kFileSystemTypeTemporary, "http://bar.com/", "001" PS "t"}, 46 {storage::kFileSystemTypePersistent, "http://bar.com/", "001" PS "p"}, 47 {storage::kFileSystemTypeTemporary, "https://foo:2/", "002" PS "t"}, 48 {storage::kFileSystemTypePersistent, "https://foo:2/", "002" PS "p"}, 49 {storage::kFileSystemTypeTemporary, "https://bar.com/", "003" PS "t"}, 50 {storage::kFileSystemTypePersistent, "https://bar.com/", "003" PS "p"}, 51}; 52 53const struct RootPathFileURITest { 54 storage::FileSystemType type; 55 const char* origin_url; 56 const char* expected_path; 57 const char* virtual_path; 58} kRootPathFileURITestCases[] = { 59 {storage::kFileSystemTypeTemporary, "file:///", "000" PS "t", NULL}, 60 {storage::kFileSystemTypePersistent, "file:///", "000" PS "p", NULL}, 61}; 62 63void DidOpenFileSystem(base::File::Error* error_out, 64 const GURL& origin_url, 65 const std::string& name, 66 base::File::Error error) { 67 *error_out = error; 68} 69 70} // namespace 71 72class SandboxFileSystemBackendTest : public testing::Test { 73 protected: 74 virtual void SetUp() { 75 ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); 76 SetUpNewDelegate(CreateAllowFileAccessOptions()); 77 } 78 79 void SetUpNewDelegate(const storage::FileSystemOptions& options) { 80 delegate_.reset(new SandboxFileSystemBackendDelegate( 81 NULL /* quota_manager_proxy */, 82 base::MessageLoopProxy::current().get(), 83 data_dir_.path(), 84 NULL /* special_storage_policy */, 85 options)); 86 } 87 88 void SetUpNewBackend(const storage::FileSystemOptions& options) { 89 SetUpNewDelegate(options); 90 backend_.reset(new SandboxFileSystemBackend(delegate_.get())); 91 } 92 93 storage::SandboxFileSystemBackendDelegate::OriginEnumerator* 94 CreateOriginEnumerator() const { 95 return backend_->CreateOriginEnumerator(); 96 } 97 98 void CreateOriginTypeDirectory(const GURL& origin, 99 storage::FileSystemType type) { 100 base::FilePath target = delegate_-> 101 GetBaseDirectoryForOriginAndType(origin, type, true); 102 ASSERT_TRUE(!target.empty()); 103 ASSERT_TRUE(base::DirectoryExists(target)); 104 } 105 106 bool GetRootPath(const GURL& origin_url, 107 storage::FileSystemType type, 108 storage::OpenFileSystemMode mode, 109 base::FilePath* root_path) { 110 base::File::Error error = base::File::FILE_OK; 111 backend_->ResolveURL( 112 FileSystemURL::CreateForTest(origin_url, type, base::FilePath()), 113 mode, 114 base::Bind(&DidOpenFileSystem, &error)); 115 base::RunLoop().RunUntilIdle(); 116 if (error != base::File::FILE_OK) 117 return false; 118 base::FilePath returned_root_path = 119 delegate_->GetBaseDirectoryForOriginAndType( 120 origin_url, type, false /* create */); 121 if (root_path) 122 *root_path = returned_root_path; 123 return !returned_root_path.empty(); 124 } 125 126 base::FilePath file_system_path() const { 127 return data_dir_.path().Append( 128 SandboxFileSystemBackendDelegate::kFileSystemDirectory); 129 } 130 131 base::ScopedTempDir data_dir_; 132 base::MessageLoop message_loop_; 133 scoped_ptr<storage::SandboxFileSystemBackendDelegate> delegate_; 134 scoped_ptr<storage::SandboxFileSystemBackend> backend_; 135}; 136 137TEST_F(SandboxFileSystemBackendTest, Empty) { 138 SetUpNewBackend(CreateAllowFileAccessOptions()); 139 scoped_ptr<SandboxFileSystemBackendDelegate::OriginEnumerator> enumerator( 140 CreateOriginEnumerator()); 141 ASSERT_TRUE(enumerator->Next().is_empty()); 142} 143 144TEST_F(SandboxFileSystemBackendTest, EnumerateOrigins) { 145 SetUpNewBackend(CreateAllowFileAccessOptions()); 146 const char* temporary_origins[] = { 147 "http://www.bar.com/", 148 "http://www.foo.com/", 149 "http://www.foo.com:1/", 150 "http://www.example.com:8080/", 151 "http://www.google.com:80/", 152 }; 153 const char* persistent_origins[] = { 154 "http://www.bar.com/", 155 "http://www.foo.com:8080/", 156 "http://www.foo.com:80/", 157 }; 158 size_t temporary_size = ARRAYSIZE_UNSAFE(temporary_origins); 159 size_t persistent_size = ARRAYSIZE_UNSAFE(persistent_origins); 160 std::set<GURL> temporary_set, persistent_set; 161 for (size_t i = 0; i < temporary_size; ++i) { 162 CreateOriginTypeDirectory(GURL(temporary_origins[i]), 163 storage::kFileSystemTypeTemporary); 164 temporary_set.insert(GURL(temporary_origins[i])); 165 } 166 for (size_t i = 0; i < persistent_size; ++i) { 167 CreateOriginTypeDirectory(GURL(persistent_origins[i]), 168 storage::kFileSystemTypePersistent); 169 persistent_set.insert(GURL(persistent_origins[i])); 170 } 171 172 scoped_ptr<SandboxFileSystemBackendDelegate::OriginEnumerator> enumerator( 173 CreateOriginEnumerator()); 174 size_t temporary_actual_size = 0; 175 size_t persistent_actual_size = 0; 176 GURL current; 177 while (!(current = enumerator->Next()).is_empty()) { 178 SCOPED_TRACE(testing::Message() << "EnumerateOrigin " << current.spec()); 179 if (enumerator->HasFileSystemType(storage::kFileSystemTypeTemporary)) { 180 ASSERT_TRUE(temporary_set.find(current) != temporary_set.end()); 181 ++temporary_actual_size; 182 } 183 if (enumerator->HasFileSystemType(storage::kFileSystemTypePersistent)) { 184 ASSERT_TRUE(persistent_set.find(current) != persistent_set.end()); 185 ++persistent_actual_size; 186 } 187 } 188 189 EXPECT_EQ(temporary_size, temporary_actual_size); 190 EXPECT_EQ(persistent_size, persistent_actual_size); 191} 192 193TEST_F(SandboxFileSystemBackendTest, GetRootPathCreateAndExamine) { 194 std::vector<base::FilePath> returned_root_path( 195 ARRAYSIZE_UNSAFE(kRootPathTestCases)); 196 SetUpNewBackend(CreateAllowFileAccessOptions()); 197 198 // Create a new root directory. 199 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) { 200 SCOPED_TRACE(testing::Message() << "RootPath (create) #" << i << " " 201 << kRootPathTestCases[i].expected_path); 202 203 base::FilePath root_path; 204 EXPECT_TRUE(GetRootPath(GURL(kRootPathTestCases[i].origin_url), 205 kRootPathTestCases[i].type, 206 storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, 207 &root_path)); 208 209 base::FilePath expected = file_system_path().AppendASCII( 210 kRootPathTestCases[i].expected_path); 211 EXPECT_EQ(expected.value(), root_path.value()); 212 EXPECT_TRUE(base::DirectoryExists(root_path)); 213 ASSERT_TRUE(returned_root_path.size() > i); 214 returned_root_path[i] = root_path; 215 } 216 217 // Get the root directory with create=false and see if we get the 218 // same directory. 219 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) { 220 SCOPED_TRACE(testing::Message() << "RootPath (get) #" << i << " " 221 << kRootPathTestCases[i].expected_path); 222 223 base::FilePath root_path; 224 EXPECT_TRUE(GetRootPath(GURL(kRootPathTestCases[i].origin_url), 225 kRootPathTestCases[i].type, 226 storage::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT, 227 &root_path)); 228 ASSERT_TRUE(returned_root_path.size() > i); 229 EXPECT_EQ(returned_root_path[i].value(), root_path.value()); 230 } 231} 232 233TEST_F(SandboxFileSystemBackendTest, 234 GetRootPathCreateAndExamineWithNewBackend) { 235 std::vector<base::FilePath> returned_root_path( 236 ARRAYSIZE_UNSAFE(kRootPathTestCases)); 237 SetUpNewBackend(CreateAllowFileAccessOptions()); 238 239 GURL origin_url("http://foo.com:1/"); 240 241 base::FilePath root_path1; 242 EXPECT_TRUE(GetRootPath(origin_url, 243 storage::kFileSystemTypeTemporary, 244 storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, 245 &root_path1)); 246 247 SetUpNewBackend(CreateDisallowFileAccessOptions()); 248 base::FilePath root_path2; 249 EXPECT_TRUE(GetRootPath(origin_url, 250 storage::kFileSystemTypeTemporary, 251 storage::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT, 252 &root_path2)); 253 254 EXPECT_EQ(root_path1.value(), root_path2.value()); 255} 256 257TEST_F(SandboxFileSystemBackendTest, GetRootPathGetWithoutCreate) { 258 SetUpNewBackend(CreateDisallowFileAccessOptions()); 259 260 // Try to get a root directory without creating. 261 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) { 262 SCOPED_TRACE(testing::Message() << "RootPath (create=false) #" << i << " " 263 << kRootPathTestCases[i].expected_path); 264 EXPECT_FALSE(GetRootPath(GURL(kRootPathTestCases[i].origin_url), 265 kRootPathTestCases[i].type, 266 storage::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT, 267 NULL)); 268 } 269} 270 271TEST_F(SandboxFileSystemBackendTest, GetRootPathInIncognito) { 272 SetUpNewBackend(CreateIncognitoFileSystemOptions()); 273 274 // Try to get a root directory. 275 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) { 276 SCOPED_TRACE(testing::Message() << "RootPath (incognito) #" << i << " " 277 << kRootPathTestCases[i].expected_path); 278 EXPECT_FALSE(GetRootPath(GURL(kRootPathTestCases[i].origin_url), 279 kRootPathTestCases[i].type, 280 storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, 281 NULL)); 282 } 283} 284 285TEST_F(SandboxFileSystemBackendTest, GetRootPathFileURI) { 286 SetUpNewBackend(CreateDisallowFileAccessOptions()); 287 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathFileURITestCases); ++i) { 288 SCOPED_TRACE(testing::Message() << "RootPathFileURI (disallow) #" 289 << i << " " << kRootPathFileURITestCases[i].expected_path); 290 EXPECT_FALSE(GetRootPath(GURL(kRootPathFileURITestCases[i].origin_url), 291 kRootPathFileURITestCases[i].type, 292 storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, 293 NULL)); 294 } 295} 296 297TEST_F(SandboxFileSystemBackendTest, GetRootPathFileURIWithAllowFlag) { 298 SetUpNewBackend(CreateAllowFileAccessOptions()); 299 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathFileURITestCases); ++i) { 300 SCOPED_TRACE(testing::Message() << "RootPathFileURI (allow) #" 301 << i << " " << kRootPathFileURITestCases[i].expected_path); 302 base::FilePath root_path; 303 EXPECT_TRUE(GetRootPath(GURL(kRootPathFileURITestCases[i].origin_url), 304 kRootPathFileURITestCases[i].type, 305 storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, 306 &root_path)); 307 base::FilePath expected = file_system_path().AppendASCII( 308 kRootPathFileURITestCases[i].expected_path); 309 EXPECT_EQ(expected.value(), root_path.value()); 310 EXPECT_TRUE(base::DirectoryExists(root_path)); 311 } 312} 313 314} // namespace content 315