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 29namespace chromeos { 30namespace file_system_provider { 31namespace util { 32 33namespace { 34 35const char kExtensionId[] = "mbflcebpggnecokmikipoihdbecnjfoj"; 36const char kFileSystemId[] = "File/System/Id"; 37const char kDisplayName[] = "Camera Pictures"; 38 39// Creates a FileSystemURL for tests. 40storage::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(). 60KeyedService* CreateService(content::BrowserContext* context) { 61 return new Service(Profile::FromBrowserContext(context), 62 extensions::ExtensionRegistry::Get(context)); 63} 64 65} // namespace 66 67class 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 100TEST_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 109TEST_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 129TEST_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 153TEST_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 176TEST_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 195TEST_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 241TEST_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 265TEST_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 286TEST_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