Home | History | Annotate | Download | only in fileapi
      1 // Copyright (c) 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/file_system_context.h"
      6 
      7 #include "base/files/scoped_temp_dir.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "base/strings/stringprintf.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 #include "webkit/browser/fileapi/external_mount_points.h"
     12 #include "webkit/browser/fileapi/file_system_backend.h"
     13 #include "webkit/browser/fileapi/isolated_context.h"
     14 #include "webkit/browser/fileapi/mock_file_system_options.h"
     15 #include "webkit/browser/quota/mock_quota_manager.h"
     16 #include "webkit/browser/quota/mock_special_storage_policy.h"
     17 
     18 #define FPL(x) FILE_PATH_LITERAL(x)
     19 
     20 #if defined(FILE_PATH_USES_DRIVE_LETTERS)
     21 #define DRIVE FPL("C:")
     22 #else
     23 #define DRIVE
     24 #endif
     25 
     26 namespace fileapi {
     27 
     28 namespace {
     29 
     30 const char kTestOrigin[] = "http://chromium.org/";
     31 const base::FilePath::CharType kVirtualPathNoRoot[] = FPL("root/file");
     32 
     33 GURL CreateRawFileSystemURL(const std::string& type_str,
     34                             const std::string& fs_id) {
     35   std::string url_str = base::StringPrintf(
     36       "filesystem:http://chromium.org/%s/%s/root/file",
     37       type_str.c_str(),
     38       fs_id.c_str());
     39   return GURL(url_str);
     40 }
     41 
     42 class FileSystemContextTest : public testing::Test {
     43  public:
     44   FileSystemContextTest() {}
     45 
     46   virtual void SetUp() {
     47     ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
     48 
     49     storage_policy_ = new quota::MockSpecialStoragePolicy();
     50 
     51     mock_quota_manager_ =
     52         new quota::MockQuotaManager(false /* is_incognito */,
     53                                     data_dir_.path(),
     54                                     base::MessageLoopProxy::current().get(),
     55                                     base::MessageLoopProxy::current().get(),
     56                                     storage_policy_.get());
     57   }
     58 
     59  protected:
     60   FileSystemContext* CreateFileSystemContextForTest(
     61       ExternalMountPoints* external_mount_points) {
     62     return new FileSystemContext(base::MessageLoopProxy::current().get(),
     63                                  base::MessageLoopProxy::current().get(),
     64                                  external_mount_points,
     65                                  storage_policy_.get(),
     66                                  mock_quota_manager_->proxy(),
     67                                  ScopedVector<FileSystemBackend>(),
     68                                  data_dir_.path(),
     69                                  CreateAllowFileAccessOptions());
     70   }
     71 
     72   // Verifies a *valid* filesystem url has expected values.
     73   void ExpectFileSystemURLMatches(const FileSystemURL& url,
     74                                   const GURL& expect_origin,
     75                                   FileSystemType expect_mount_type,
     76                                   FileSystemType expect_type,
     77                                   const base::FilePath& expect_path,
     78                                   const base::FilePath& expect_virtual_path,
     79                                   const std::string& expect_filesystem_id) {
     80     EXPECT_TRUE(url.is_valid());
     81 
     82     EXPECT_EQ(expect_origin, url.origin());
     83     EXPECT_EQ(expect_mount_type, url.mount_type());
     84     EXPECT_EQ(expect_type, url.type());
     85     EXPECT_EQ(expect_path, url.path());
     86     EXPECT_EQ(expect_virtual_path, url.virtual_path());
     87     EXPECT_EQ(expect_filesystem_id, url.filesystem_id());
     88   }
     89 
     90  private:
     91   base::ScopedTempDir data_dir_;
     92   base::MessageLoop message_loop_;
     93   scoped_refptr<quota::SpecialStoragePolicy> storage_policy_;
     94   scoped_refptr<quota::MockQuotaManager> mock_quota_manager_;
     95 };
     96 
     97 // It is not valid to pass NULL ExternalMountPoints to FileSystemContext on
     98 // ChromeOS.
     99 #if !defined(OS_CHROMEOS)
    100 TEST_F(FileSystemContextTest, NullExternalMountPoints) {
    101   scoped_refptr<FileSystemContext> file_system_context(
    102       CreateFileSystemContextForTest(NULL));
    103 
    104   // Cracking system external mount and isolated mount points should work.
    105   std::string isolated_name = "root";
    106   std::string isolated_id =
    107       IsolatedContext::GetInstance()->RegisterFileSystemForPath(
    108           kFileSystemTypeNativeLocal,
    109           base::FilePath(DRIVE FPL("/test/isolated/root")),
    110           &isolated_name);
    111   // Register system external mount point.
    112   ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
    113       "system",
    114       kFileSystemTypeNativeLocal,
    115       base::FilePath(DRIVE FPL("/test/sys/"))));
    116 
    117   FileSystemURL cracked_isolated = file_system_context->CrackURL(
    118       CreateRawFileSystemURL("isolated", isolated_id));
    119 
    120   ExpectFileSystemURLMatches(
    121       cracked_isolated,
    122       GURL(kTestOrigin),
    123       kFileSystemTypeIsolated,
    124       kFileSystemTypeNativeLocal,
    125       base::FilePath(DRIVE FPL("/test/isolated/root/file")).NormalizePathSeparators(),
    126       base::FilePath::FromUTF8Unsafe(isolated_id).Append(FPL("root/file")).
    127           NormalizePathSeparators(),
    128       isolated_id);
    129 
    130   FileSystemURL cracked_external = file_system_context->CrackURL(
    131       CreateRawFileSystemURL("external", "system"));
    132 
    133   ExpectFileSystemURLMatches(
    134       cracked_external,
    135       GURL(kTestOrigin),
    136       kFileSystemTypeExternal,
    137       kFileSystemTypeNativeLocal,
    138       base::FilePath(
    139           DRIVE FPL("/test/sys/root/file")).NormalizePathSeparators(),
    140       base::FilePath(FPL("system/root/file")).NormalizePathSeparators(),
    141       "system");
    142 
    143 
    144   IsolatedContext::GetInstance()->RevokeFileSystem(isolated_id);
    145   ExternalMountPoints::GetSystemInstance()->RevokeFileSystem("system");
    146 }
    147 #endif  // !defiend(OS_CHROMEOS)
    148 
    149 TEST_F(FileSystemContextTest, FileSystemContextKeepsMountPointsAlive) {
    150   scoped_refptr<ExternalMountPoints> mount_points =
    151       ExternalMountPoints::CreateRefCounted();
    152 
    153   // Register system external mount point.
    154   ASSERT_TRUE(mount_points->RegisterFileSystem(
    155       "system",
    156       kFileSystemTypeNativeLocal,
    157       base::FilePath(DRIVE FPL("/test/sys/"))));
    158 
    159   scoped_refptr<FileSystemContext> file_system_context(
    160       CreateFileSystemContextForTest(mount_points.get()));
    161 
    162   // Release a MountPoints reference created in the test.
    163   mount_points = NULL;
    164 
    165   // FileSystemContext should keep a reference to the |mount_points|, so it
    166   // should be able to resolve the URL.
    167   FileSystemURL cracked_external = file_system_context->CrackURL(
    168       CreateRawFileSystemURL("external", "system"));
    169 
    170   ExpectFileSystemURLMatches(
    171       cracked_external,
    172       GURL(kTestOrigin),
    173       kFileSystemTypeExternal,
    174       kFileSystemTypeNativeLocal,
    175       base::FilePath(
    176           DRIVE FPL("/test/sys/root/file")).NormalizePathSeparators(),
    177       base::FilePath(FPL("system/root/file")).NormalizePathSeparators(),
    178       "system");
    179 
    180   // No need to revoke the registered filesystem since |mount_points| lifetime
    181   // is bound to this test.
    182 }
    183 
    184 TEST_F(FileSystemContextTest, CrackFileSystemURL) {
    185   scoped_refptr<ExternalMountPoints> external_mount_points(
    186       ExternalMountPoints::CreateRefCounted());
    187   scoped_refptr<FileSystemContext> file_system_context(
    188       CreateFileSystemContextForTest(external_mount_points.get()));
    189 
    190   // Register an isolated mount point.
    191   std::string isolated_file_system_name = "root";
    192   const std::string kIsolatedFileSystemID =
    193       IsolatedContext::GetInstance()->RegisterFileSystemForPath(
    194           kFileSystemTypeNativeLocal,
    195           base::FilePath(DRIVE FPL("/test/isolated/root")),
    196           &isolated_file_system_name);
    197   // Register system external mount point.
    198   ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
    199       "system",
    200       kFileSystemTypeDrive,
    201       base::FilePath(DRIVE FPL("/test/sys/"))));
    202   ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
    203       "ext",
    204       kFileSystemTypeNativeLocal,
    205       base::FilePath(DRIVE FPL("/test/ext"))));
    206   // Register a system external mount point with the same name/id as the
    207   // registered isolated mount point.
    208   ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
    209       kIsolatedFileSystemID,
    210       kFileSystemTypeRestrictedNativeLocal,
    211       base::FilePath(DRIVE FPL("/test/system/isolated"))));
    212   // Add a mount points with the same name as a system mount point to
    213   // FileSystemContext's external mount points.
    214   ASSERT_TRUE(external_mount_points->RegisterFileSystem(
    215       "ext",
    216        kFileSystemTypeNativeLocal,
    217        base::FilePath(DRIVE FPL("/test/local/ext/"))));
    218 
    219   const GURL kTestOrigin = GURL("http://chromium.org/");
    220   const base::FilePath kVirtualPathNoRoot = base::FilePath(FPL("root/file"));
    221 
    222   struct TestCase {
    223     // Test case values.
    224     std::string root;
    225     std::string type_str;
    226 
    227     // Expected test results.
    228     bool expect_is_valid;
    229     FileSystemType expect_mount_type;
    230     FileSystemType expect_type;
    231     const base::FilePath::CharType* expect_path;
    232     std::string expect_filesystem_id;
    233   };
    234 
    235   const TestCase kTestCases[] = {
    236       // Following should not be handled by the url crackers:
    237       {
    238         "pers_mount", "persistent", true /* is_valid */,
    239         kFileSystemTypePersistent, kFileSystemTypePersistent,
    240         FPL("pers_mount/root/file"),
    241         std::string()  /* filesystem id */
    242       },
    243       {
    244         "temp_mount", "temporary", true /* is_valid */,
    245         kFileSystemTypeTemporary, kFileSystemTypeTemporary,
    246         FPL("temp_mount/root/file"),
    247         std::string()  /* filesystem id */
    248       },
    249       // Should be cracked by isolated mount points:
    250       {
    251         kIsolatedFileSystemID, "isolated", true /* is_valid */,
    252         kFileSystemTypeIsolated, kFileSystemTypeNativeLocal,
    253         DRIVE FPL("/test/isolated/root/file"),
    254         kIsolatedFileSystemID
    255       },
    256       // Should be cracked by system mount points:
    257       {
    258         "system", "external", true /* is_valid */,
    259         kFileSystemTypeExternal, kFileSystemTypeDrive,
    260         DRIVE FPL("/test/sys/root/file"),
    261         "system"
    262       },
    263       {
    264         kIsolatedFileSystemID, "external", true /* is_valid */,
    265         kFileSystemTypeExternal, kFileSystemTypeRestrictedNativeLocal,
    266         DRIVE FPL("/test/system/isolated/root/file"),
    267         kIsolatedFileSystemID
    268       },
    269       // Should be cracked by FileSystemContext's ExternalMountPoints.
    270       {
    271         "ext", "external", true /* is_valid */,
    272         kFileSystemTypeExternal, kFileSystemTypeNativeLocal,
    273         DRIVE FPL("/test/local/ext/root/file"),
    274         "ext"
    275       },
    276       // Test for invalid filesystem url (made invalid by adding invalid
    277       // filesystem type).
    278       {
    279         "sytem", "external", false /* is_valid */,
    280         // The rest of values will be ignored.
    281         kFileSystemTypeUnknown, kFileSystemTypeUnknown, FPL(""),
    282         std::string()
    283       },
    284       // Test for URL with non-existing filesystem id.
    285       {
    286         "invalid", "external", false /* is_valid */,
    287         // The rest of values will be ignored.
    288         kFileSystemTypeUnknown, kFileSystemTypeUnknown, FPL(""),
    289         std::string()
    290       },
    291   };
    292 
    293   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
    294     const base::FilePath virtual_path =
    295         base::FilePath::FromUTF8Unsafe(kTestCases[i].root).Append(kVirtualPathNoRoot);
    296 
    297     GURL raw_url =
    298         CreateRawFileSystemURL(kTestCases[i].type_str, kTestCases[i].root);
    299     FileSystemURL cracked_url = file_system_context->CrackURL(raw_url);
    300 
    301     SCOPED_TRACE(testing::Message() << "Test case " << i << ": "
    302                                     << "Cracking URL: " << raw_url);
    303 
    304     EXPECT_EQ(kTestCases[i].expect_is_valid, cracked_url.is_valid());
    305     if (!kTestCases[i].expect_is_valid)
    306       continue;
    307 
    308     ExpectFileSystemURLMatches(
    309         cracked_url,
    310         GURL(kTestOrigin),
    311         kTestCases[i].expect_mount_type,
    312         kTestCases[i].expect_type,
    313         base::FilePath(kTestCases[i].expect_path).NormalizePathSeparators(),
    314         virtual_path.NormalizePathSeparators(),
    315         kTestCases[i].expect_filesystem_id);
    316   }
    317 
    318   IsolatedContext::GetInstance()->RevokeFileSystemByPath(
    319       base::FilePath(DRIVE FPL("/test/isolated/root")));
    320   ExternalMountPoints::GetSystemInstance()->RevokeFileSystem("system");
    321   ExternalMountPoints::GetSystemInstance()->RevokeFileSystem("ext");
    322   ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
    323       kIsolatedFileSystemID);
    324 }
    325 
    326 }  // namespace
    327 
    328 }  // namespace fileapi
    329