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