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