Home | History | Annotate | Download | only in file_system_provider
      1 // Copyright 2014 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 "chrome/browser/chromeos/file_system_provider/mount_path_util.h"
      6 
      7 #include <string>
      8 
      9 #include "base/files/file.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h"
     12 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h"
     13 #include "chrome/browser/chromeos/file_system_provider/service.h"
     14 #include "chrome/browser/chromeos/file_system_provider/service_factory.h"
     15 #include "chrome/browser/chromeos/login/users/fake_user_manager.h"
     16 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
     17 #include "chrome/browser/profiles/profile.h"
     18 #include "chrome/test/base/testing_browser_process.h"
     19 #include "chrome/test/base/testing_profile.h"
     20 #include "chrome/test/base/testing_profile_manager.h"
     21 #include "components/keyed_service/core/keyed_service.h"
     22 #include "content/public/browser/browser_context.h"
     23 #include "content/public/test/test_browser_thread_bundle.h"
     24 #include "extensions/browser/extension_registry.h"
     25 #include "storage/browser/fileapi/external_mount_points.h"
     26 #include "storage/browser/fileapi/isolated_context.h"
     27 #include "testing/gtest/include/gtest/gtest.h"
     28 
     29 namespace chromeos {
     30 namespace file_system_provider {
     31 namespace util {
     32 
     33 namespace {
     34 
     35 const char kExtensionId[] = "mbflcebpggnecokmikipoihdbecnjfoj";
     36 const char kFileSystemId[] = "File/System/Id";
     37 const char kDisplayName[] = "Camera Pictures";
     38 
     39 // Creates a FileSystemURL for tests.
     40 storage::FileSystemURL CreateFileSystemURL(
     41     Profile* profile,
     42     const ProvidedFileSystemInfo& file_system_info,
     43     const base::FilePath& file_path) {
     44   const std::string origin =
     45       std::string("chrome-extension://") + file_system_info.extension_id();
     46   const base::FilePath mount_path = file_system_info.mount_path();
     47   const storage::ExternalMountPoints* const mount_points =
     48       storage::ExternalMountPoints::GetSystemInstance();
     49   DCHECK(mount_points);
     50   DCHECK(file_path.IsAbsolute());
     51   base::FilePath relative_path(file_path.value().substr(1));
     52   return mount_points->CreateCrackedFileSystemURL(
     53       GURL(origin),
     54       storage::kFileSystemTypeExternal,
     55       base::FilePath(mount_path.BaseName().Append(relative_path)));
     56 }
     57 
     58 // Creates a Service instance. Used to be able to destroy the service in
     59 // TearDown().
     60 KeyedService* CreateService(content::BrowserContext* context) {
     61   return new Service(Profile::FromBrowserContext(context),
     62                      extensions::ExtensionRegistry::Get(context));
     63 }
     64 
     65 }  // namespace
     66 
     67 class FileSystemProviderMountPathUtilTest : public testing::Test {
     68  protected:
     69   FileSystemProviderMountPathUtilTest() {}
     70   virtual ~FileSystemProviderMountPathUtilTest() {}
     71 
     72   virtual void SetUp() OVERRIDE {
     73     profile_manager_.reset(
     74         new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
     75     ASSERT_TRUE(profile_manager_->SetUp());
     76     profile_ = profile_manager_->CreateTestingProfile("testing-profile");
     77     user_manager_ = new FakeUserManager();
     78     user_manager_enabler_.reset(new ScopedUserManagerEnabler(user_manager_));
     79     user_manager_->AddUser(profile_->GetProfileName());
     80     ServiceFactory::GetInstance()->SetTestingFactory(profile_, &CreateService);
     81     file_system_provider_service_ = Service::Get(profile_);
     82     file_system_provider_service_->SetFileSystemFactoryForTesting(
     83         base::Bind(&FakeProvidedFileSystem::Create));
     84   }
     85 
     86   virtual void TearDown() OVERRIDE {
     87     // Setting the testing factory to NULL will destroy the created service
     88     // associated with the testing profile.
     89     ServiceFactory::GetInstance()->SetTestingFactory(profile_, NULL);
     90   }
     91 
     92   content::TestBrowserThreadBundle thread_bundle_;
     93   scoped_ptr<TestingProfileManager> profile_manager_;
     94   TestingProfile* profile_;  // Owned by TestingProfileManager.
     95   scoped_ptr<ScopedUserManagerEnabler> user_manager_enabler_;
     96   FakeUserManager* user_manager_;
     97   Service* file_system_provider_service_;  // Owned by its factory.
     98 };
     99 
    100 TEST_F(FileSystemProviderMountPathUtilTest, GetMountPath) {
    101   const base::FilePath result =
    102       GetMountPath(profile_, kExtensionId, kFileSystemId);
    103   const std::string expected =
    104       "/provided/mbflcebpggnecokmikipoihdbecnjfoj:"
    105       "File%2FSystem%2FId:testing-profile-hash";
    106   EXPECT_EQ(expected, result.AsUTF8Unsafe());
    107 }
    108 
    109 TEST_F(FileSystemProviderMountPathUtilTest, IsFileSystemProviderLocalPath) {
    110   const base::FilePath mount_path =
    111       GetMountPath(profile_, kExtensionId, kFileSystemId);
    112   const base::FilePath file_path =
    113       base::FilePath::FromUTF8Unsafe("/hello/world.txt");
    114   const base::FilePath local_file_path =
    115       mount_path.Append(base::FilePath(file_path.value().substr(1)));
    116 
    117   EXPECT_TRUE(IsFileSystemProviderLocalPath(mount_path));
    118   EXPECT_TRUE(IsFileSystemProviderLocalPath(local_file_path));
    119 
    120   EXPECT_FALSE(IsFileSystemProviderLocalPath(
    121       base::FilePath::FromUTF8Unsafe("provided/hello-world/test.txt")));
    122   EXPECT_FALSE(IsFileSystemProviderLocalPath(
    123       base::FilePath::FromUTF8Unsafe("/provided")));
    124   EXPECT_FALSE(
    125       IsFileSystemProviderLocalPath(base::FilePath::FromUTF8Unsafe("/")));
    126   EXPECT_FALSE(IsFileSystemProviderLocalPath(base::FilePath()));
    127 }
    128 
    129 TEST_F(FileSystemProviderMountPathUtilTest, Parser) {
    130   const bool result = file_system_provider_service_->MountFileSystem(
    131       kExtensionId, kFileSystemId, kDisplayName, false /* writable */);
    132   ASSERT_TRUE(result);
    133   const ProvidedFileSystemInfo file_system_info =
    134       file_system_provider_service_->GetProvidedFileSystem(kExtensionId,
    135                                                            kFileSystemId)
    136           ->GetFileSystemInfo();
    137 
    138   const base::FilePath kFilePath =
    139       base::FilePath::FromUTF8Unsafe("/hello/world.txt");
    140   const storage::FileSystemURL url =
    141       CreateFileSystemURL(profile_, file_system_info, kFilePath);
    142   EXPECT_TRUE(url.is_valid());
    143 
    144   FileSystemURLParser parser(url);
    145   EXPECT_TRUE(parser.Parse());
    146 
    147   ProvidedFileSystemInterface* file_system = parser.file_system();
    148   ASSERT_TRUE(file_system);
    149   EXPECT_EQ(kFileSystemId, file_system->GetFileSystemInfo().file_system_id());
    150   EXPECT_EQ(kFilePath.AsUTF8Unsafe(), parser.file_path().AsUTF8Unsafe());
    151 }
    152 
    153 TEST_F(FileSystemProviderMountPathUtilTest, Parser_RootPath) {
    154   const bool result = file_system_provider_service_->MountFileSystem(
    155       kExtensionId, kFileSystemId, kDisplayName, false /* writable */);
    156   ASSERT_TRUE(result);
    157   const ProvidedFileSystemInfo file_system_info =
    158       file_system_provider_service_->GetProvidedFileSystem(kExtensionId,
    159                                                            kFileSystemId)
    160           ->GetFileSystemInfo();
    161 
    162   const base::FilePath kFilePath = base::FilePath::FromUTF8Unsafe("/");
    163   const storage::FileSystemURL url =
    164       CreateFileSystemURL(profile_, file_system_info, kFilePath);
    165   EXPECT_TRUE(url.is_valid());
    166 
    167   FileSystemURLParser parser(url);
    168   EXPECT_TRUE(parser.Parse());
    169 
    170   ProvidedFileSystemInterface* file_system = parser.file_system();
    171   ASSERT_TRUE(file_system);
    172   EXPECT_EQ(kFileSystemId, file_system->GetFileSystemInfo().file_system_id());
    173   EXPECT_EQ(kFilePath.AsUTF8Unsafe(), parser.file_path().AsUTF8Unsafe());
    174 }
    175 
    176 TEST_F(FileSystemProviderMountPathUtilTest, Parser_WrongUrl) {
    177   const ProvidedFileSystemInfo file_system_info(
    178       kExtensionId,
    179       kFileSystemId,
    180       kDisplayName,
    181       false /* writable */,
    182       GetMountPath(profile_, kExtensionId, kFileSystemId));
    183 
    184   const base::FilePath kFilePath = base::FilePath::FromUTF8Unsafe("/hello");
    185   const storage::FileSystemURL url =
    186       CreateFileSystemURL(profile_, file_system_info, kFilePath);
    187   // It is impossible to create a cracked URL for a mount point which doesn't
    188   // exist, therefore is will always be invalid, and empty.
    189   EXPECT_FALSE(url.is_valid());
    190 
    191   FileSystemURLParser parser(url);
    192   EXPECT_FALSE(parser.Parse());
    193 }
    194 
    195 TEST_F(FileSystemProviderMountPathUtilTest, Parser_IsolatedURL) {
    196   const bool result = file_system_provider_service_->MountFileSystem(
    197       kExtensionId, kFileSystemId, kDisplayName, false /* writable */);
    198   ASSERT_TRUE(result);
    199   const ProvidedFileSystemInfo file_system_info =
    200       file_system_provider_service_->GetProvidedFileSystem(kExtensionId,
    201                                                            kFileSystemId)
    202           ->GetFileSystemInfo();
    203 
    204   const base::FilePath kFilePath =
    205       base::FilePath::FromUTF8Unsafe("/hello/world.txt");
    206   const storage::FileSystemURL url =
    207       CreateFileSystemURL(profile_, file_system_info, kFilePath);
    208   EXPECT_TRUE(url.is_valid());
    209 
    210   // Create an isolated URL for the original one.
    211   storage::IsolatedContext* const isolated_context =
    212       storage::IsolatedContext::GetInstance();
    213   const std::string isolated_file_system_id =
    214       isolated_context->RegisterFileSystemForPath(
    215           storage::kFileSystemTypeProvided,
    216           url.filesystem_id(),
    217           url.path(),
    218           NULL);
    219 
    220   const base::FilePath isolated_virtual_path =
    221       isolated_context->CreateVirtualRootPath(isolated_file_system_id)
    222           .Append(kFilePath.BaseName().value());
    223 
    224   const storage::FileSystemURL isolated_url =
    225       isolated_context->CreateCrackedFileSystemURL(
    226           url.origin(),
    227           storage::kFileSystemTypeIsolated,
    228           isolated_virtual_path);
    229 
    230   EXPECT_TRUE(isolated_url.is_valid());
    231 
    232   FileSystemURLParser parser(isolated_url);
    233   EXPECT_TRUE(parser.Parse());
    234 
    235   ProvidedFileSystemInterface* file_system = parser.file_system();
    236   ASSERT_TRUE(file_system);
    237   EXPECT_EQ(kFileSystemId, file_system->GetFileSystemInfo().file_system_id());
    238   EXPECT_EQ(kFilePath.AsUTF8Unsafe(), parser.file_path().AsUTF8Unsafe());
    239 }
    240 
    241 TEST_F(FileSystemProviderMountPathUtilTest, LocalPathParser) {
    242   const bool result = file_system_provider_service_->MountFileSystem(
    243       kExtensionId, kFileSystemId, kDisplayName, false /* writable */);
    244   ASSERT_TRUE(result);
    245   const ProvidedFileSystemInfo file_system_info =
    246       file_system_provider_service_->GetProvidedFileSystem(kExtensionId,
    247                                                            kFileSystemId)
    248           ->GetFileSystemInfo();
    249 
    250   const base::FilePath kFilePath =
    251       base::FilePath::FromUTF8Unsafe("/hello/world.txt");
    252   const base::FilePath kLocalFilePath = file_system_info.mount_path().Append(
    253       base::FilePath(kFilePath.value().substr(1)));
    254 
    255   LOG(ERROR) << kLocalFilePath.value();
    256   LocalPathParser parser(profile_, kLocalFilePath);
    257   EXPECT_TRUE(parser.Parse());
    258 
    259   ProvidedFileSystemInterface* file_system = parser.file_system();
    260   ASSERT_TRUE(file_system);
    261   EXPECT_EQ(kFileSystemId, file_system->GetFileSystemInfo().file_system_id());
    262   EXPECT_EQ(kFilePath.AsUTF8Unsafe(), parser.file_path().AsUTF8Unsafe());
    263 }
    264 
    265 TEST_F(FileSystemProviderMountPathUtilTest, LocalPathParser_RootPath) {
    266   const bool result = file_system_provider_service_->MountFileSystem(
    267       kExtensionId, kFileSystemId, kDisplayName, false /* writable */);
    268   ASSERT_TRUE(result);
    269   const ProvidedFileSystemInfo file_system_info =
    270       file_system_provider_service_->GetProvidedFileSystem(kExtensionId,
    271                                                            kFileSystemId)
    272           ->GetFileSystemInfo();
    273 
    274   const base::FilePath kFilePath = base::FilePath::FromUTF8Unsafe("/");
    275   const base::FilePath kLocalFilePath = file_system_info.mount_path();
    276 
    277   LocalPathParser parser(profile_, kLocalFilePath);
    278   EXPECT_TRUE(parser.Parse());
    279 
    280   ProvidedFileSystemInterface* file_system = parser.file_system();
    281   ASSERT_TRUE(file_system);
    282   EXPECT_EQ(kFileSystemId, file_system->GetFileSystemInfo().file_system_id());
    283   EXPECT_EQ(kFilePath.AsUTF8Unsafe(), parser.file_path().AsUTF8Unsafe());
    284 }
    285 
    286 TEST_F(FileSystemProviderMountPathUtilTest, LocalPathParser_WrongPath) {
    287   {
    288     const base::FilePath kFilePath = base::FilePath::FromUTF8Unsafe("/hello");
    289     LocalPathParser parser(profile_, kFilePath);
    290     EXPECT_FALSE(parser.Parse());
    291   }
    292 
    293   {
    294     const base::FilePath kFilePath =
    295         base::FilePath::FromUTF8Unsafe("/provided");
    296     LocalPathParser parser(profile_, kFilePath);
    297     EXPECT_FALSE(parser.Parse());
    298   }
    299 
    300   {
    301     const base::FilePath kFilePath =
    302         base::FilePath::FromUTF8Unsafe("provided/hello/world");
    303     LocalPathParser parser(profile_, kFilePath);
    304     EXPECT_FALSE(parser.Parse());
    305   }
    306 }
    307 
    308 }  // namespace util
    309 }  // namespace file_system_provider
    310 }  // namespace chromeos
    311