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 <string>
6
7#include "base/files/file.h"
8#include "base/memory/scoped_ptr.h"
9#include "chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h"
10#include "chrome/browser/chromeos/file_system_provider/mount_path_util.h"
11#include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h"
12#include "chrome/browser/chromeos/file_system_provider/service.h"
13#include "chrome/browser/chromeos/file_system_provider/service_factory.h"
14#include "chrome/browser/chromeos/login/users/fake_user_manager.h"
15#include "chrome/browser/profiles/profile.h"
16#include "chrome/test/base/testing_browser_process.h"
17#include "chrome/test/base/testing_profile.h"
18#include "chrome/test/base/testing_profile_manager.h"
19#include "components/keyed_service/core/keyed_service.h"
20#include "content/public/browser/browser_context.h"
21#include "content/public/test/test_browser_thread_bundle.h"
22#include "extensions/browser/extension_registry.h"
23#include "testing/gtest/include/gtest/gtest.h"
24#include "webkit/browser/fileapi/external_mount_points.h"
25
26namespace chromeos {
27namespace file_system_provider {
28namespace util {
29
30namespace {
31
32const char kExtensionId[] = "mbflcebpggnecokmikipoihdbecnjfoj";
33const char kFileSystemId[] = "File/System/Id";
34const char kFileSystemName[] = "Camera Pictures";
35
36// Creates a FileSystemURL for tests.
37fileapi::FileSystemURL CreateFileSystemURL(
38    Profile* profile,
39    const ProvidedFileSystemInfo& file_system_info,
40    const base::FilePath& file_path) {
41  const std::string origin =
42      std::string("chrome-extension://") + file_system_info.extension_id();
43  const base::FilePath mount_path = file_system_info.mount_path();
44  const fileapi::ExternalMountPoints* const mount_points =
45      fileapi::ExternalMountPoints::GetSystemInstance();
46  DCHECK(mount_points);
47  DCHECK(file_path.IsAbsolute());
48  base::FilePath relative_path(file_path.value().substr(1));
49  return mount_points->CreateCrackedFileSystemURL(
50      GURL(origin),
51      fileapi::kFileSystemTypeExternal,
52      base::FilePath(mount_path.BaseName().Append(relative_path)));
53}
54
55// Creates a Service instance. Used to be able to destroy the service in
56// TearDown().
57KeyedService* CreateService(content::BrowserContext* context) {
58  return new Service(Profile::FromBrowserContext(context),
59                     extensions::ExtensionRegistry::Get(context));
60}
61
62}  // namespace
63
64class FileSystemProviderMountPathUtilTest : public testing::Test {
65 protected:
66  FileSystemProviderMountPathUtilTest() {}
67  virtual ~FileSystemProviderMountPathUtilTest() {}
68
69  virtual void SetUp() OVERRIDE {
70    profile_manager_.reset(
71        new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
72    ASSERT_TRUE(profile_manager_->SetUp());
73    profile_ = profile_manager_->CreateTestingProfile("testing-profile");
74    user_manager_ = new FakeUserManager();
75    user_manager_enabler_.reset(new ScopedUserManagerEnabler(user_manager_));
76    user_manager_->AddUser(profile_->GetProfileName());
77    ServiceFactory::GetInstance()->SetTestingFactory(profile_, &CreateService);
78    file_system_provider_service_ = Service::Get(profile_);
79    file_system_provider_service_->SetFileSystemFactoryForTesting(
80        base::Bind(&FakeProvidedFileSystem::Create));
81  }
82
83  virtual void TearDown() OVERRIDE {
84    // Setting the testing factory to NULL will destroy the created service
85    // associated with the testing profile.
86    ServiceFactory::GetInstance()->SetTestingFactory(profile_, NULL);
87  }
88
89  content::TestBrowserThreadBundle thread_bundle_;
90  scoped_ptr<TestingProfileManager> profile_manager_;
91  TestingProfile* profile_;  // Owned by TestingProfileManager.
92  scoped_ptr<ScopedUserManagerEnabler> user_manager_enabler_;
93  FakeUserManager* user_manager_;
94  Service* file_system_provider_service_;  // Owned by its factory.
95};
96
97TEST_F(FileSystemProviderMountPathUtilTest, GetMountPath) {
98  base::FilePath result = GetMountPath(profile_, kExtensionId, kFileSystemId);
99  const std::string expected =
100      "/provided/mbflcebpggnecokmikipoihdbecnjfoj:"
101      "File%2FSystem%2FId:testing-profile-hash";
102  EXPECT_EQ(expected, result.AsUTF8Unsafe());
103}
104
105TEST_F(FileSystemProviderMountPathUtilTest, Parser) {
106  const bool result = file_system_provider_service_->MountFileSystem(
107      kExtensionId, kFileSystemId, kFileSystemName);
108  ASSERT_TRUE(result);
109  const ProvidedFileSystemInfo file_system_info =
110      file_system_provider_service_->GetProvidedFileSystem(kExtensionId,
111                                                           kFileSystemId)
112          ->GetFileSystemInfo();
113
114  const base::FilePath kFilePath =
115      base::FilePath::FromUTF8Unsafe("/hello/world.txt");
116  const fileapi::FileSystemURL url =
117      CreateFileSystemURL(profile_, file_system_info, kFilePath);
118  EXPECT_TRUE(url.is_valid());
119
120  FileSystemURLParser parser(url);
121  EXPECT_TRUE(parser.Parse());
122
123  ProvidedFileSystemInterface* file_system = parser.file_system();
124  ASSERT_TRUE(file_system);
125  EXPECT_EQ(kFileSystemId, file_system->GetFileSystemInfo().file_system_id());
126  EXPECT_EQ(kFilePath.AsUTF8Unsafe(), parser.file_path().AsUTF8Unsafe());
127}
128
129TEST_F(FileSystemProviderMountPathUtilTest, Parser_RootPath) {
130  const bool result = file_system_provider_service_->MountFileSystem(
131      kExtensionId, kFileSystemId, kFileSystemName);
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 = base::FilePath::FromUTF8Unsafe("/");
139  const fileapi::FileSystemURL url =
140      CreateFileSystemURL(profile_, file_system_info, kFilePath);
141  EXPECT_TRUE(url.is_valid());
142
143  FileSystemURLParser parser(url);
144  EXPECT_TRUE(parser.Parse());
145
146  ProvidedFileSystemInterface* file_system = parser.file_system();
147  ASSERT_TRUE(file_system);
148  EXPECT_EQ(kFileSystemId, file_system->GetFileSystemInfo().file_system_id());
149  EXPECT_EQ(kFilePath.AsUTF8Unsafe(), parser.file_path().AsUTF8Unsafe());
150}
151
152TEST_F(FileSystemProviderMountPathUtilTest, Parser_WrongUrl) {
153  const ProvidedFileSystemInfo file_system_info(
154      kExtensionId,
155      kFileSystemId,
156      kFileSystemName,
157      GetMountPath(profile_, kExtensionId, kFileSystemId));
158
159  const base::FilePath file_path = base::FilePath::FromUTF8Unsafe("/hello");
160  const fileapi::FileSystemURL url =
161      CreateFileSystemURL(profile_, file_system_info, file_path);
162  // It is impossible to create a cracked URL for a mount point which doesn't
163  // exist, therefore is will always be invalid, and empty.
164  EXPECT_FALSE(url.is_valid());
165
166  FileSystemURLParser parser(url);
167  EXPECT_FALSE(parser.Parse());
168}
169
170}  // namespace util
171}  // namespace file_system_provider
172}  // namespace chromeos
173