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.
5 #include "chrome/browser/chromeos/file_system_provider/registry.h"
10 #include "base/files/file_path.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_info.h"
13 #include "chrome/common/extensions/api/file_system_provider_capabilities/file_system_provider_capabilities_handler.h"
14 #include "chrome/common/pref_names.h"
15 #include "chrome/test/base/testing_browser_process.h"
16 #include "chrome/test/base/testing_profile.h"
17 #include "chrome/test/base/testing_profile_manager.h"
18 #include "components/syncable_prefs/testing_pref_service_syncable.h"
19 #include "components/user_prefs/user_prefs.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "testing/gtest/include/gtest/gtest.h"
24 namespace file_system_provider
{
27 const char kTemporaryOrigin
[] =
28 "chrome-extension://abcabcabcabcabcabcabcabcabcabcabcabca/";
29 const char kPersistentOrigin
[] =
30 "chrome-extension://efgefgefgefgefgefgefgefgefgefgefgefge/";
31 const char kExtensionId
[] = "mbflcebpggnecokmikipoihdbecnjfoj";
32 const char kDisplayName
[] = "Camera Pictures";
34 // The dot in the file system ID is there in order to check that saving to
35 // preferences works correctly. File System ID is used as a key in
36 // a base::DictionaryValue, so it has to be stored without path expansion.
37 const char kFileSystemId
[] = "camera/pictures/id .!@#$%^&*()_+";
39 const int kOpenedFilesLimit
= 5;
41 // Stores a provided file system information in preferences together with a
43 void RememberFakeFileSystem(TestingProfile
* profile
,
44 const std::string
& extension_id
,
45 const std::string
& file_system_id
,
46 const std::string
& display_name
,
48 bool supports_notify_tag
,
49 int opened_files_limit
,
50 const Watcher
& watcher
) {
51 // Warning. Updating this code means that backward compatibility may be
52 // broken, what is unexpected and should be avoided.
53 syncable_prefs::TestingPrefServiceSyncable
* const pref_service
=
54 profile
->GetTestingPrefService();
55 ASSERT_TRUE(pref_service
);
57 base::DictionaryValue extensions
;
58 base::DictionaryValue
* const file_systems
= new base::DictionaryValue();
59 base::DictionaryValue
* const file_system
= new base::DictionaryValue();
60 file_system
->SetStringWithoutPathExpansion(kPrefKeyFileSystemId
,
62 file_system
->SetStringWithoutPathExpansion(kPrefKeyDisplayName
, kDisplayName
);
63 file_system
->SetBooleanWithoutPathExpansion(kPrefKeyWritable
, writable
);
64 file_system
->SetBooleanWithoutPathExpansion(kPrefKeySupportsNotifyTag
,
66 file_system
->SetIntegerWithoutPathExpansion(kPrefKeyOpenedFilesLimit
,
68 file_systems
->SetWithoutPathExpansion(kFileSystemId
, file_system
);
69 extensions
.SetWithoutPathExpansion(kExtensionId
, file_systems
);
72 base::DictionaryValue
* const watchers
= new base::DictionaryValue();
73 file_system
->SetWithoutPathExpansion(kPrefKeyWatchers
, watchers
);
74 base::DictionaryValue
* const watcher_value
= new base::DictionaryValue();
75 watchers
->SetWithoutPathExpansion(watcher
.entry_path
.value(), watcher_value
);
76 watcher_value
->SetStringWithoutPathExpansion(kPrefKeyWatcherEntryPath
,
77 watcher
.entry_path
.value());
78 watcher_value
->SetBooleanWithoutPathExpansion(kPrefKeyWatcherRecursive
,
80 watcher_value
->SetStringWithoutPathExpansion(kPrefKeyWatcherLastTag
,
82 base::ListValue
* const persistent_origins_value
= new base::ListValue();
83 watcher_value
->SetWithoutPathExpansion(kPrefKeyWatcherPersistentOrigins
,
84 persistent_origins_value
);
85 for (const auto& subscriber_it
: watcher
.subscribers
) {
86 if (subscriber_it
.second
.persistent
)
87 persistent_origins_value
->AppendString(subscriber_it
.first
.spec());
90 pref_service
->Set(prefs::kFileSystemProviderMounted
, extensions
);
95 class FileSystemProviderRegistryTest
: public testing::Test
{
97 FileSystemProviderRegistryTest() : profile_(NULL
) {}
99 ~FileSystemProviderRegistryTest() override
{}
101 void SetUp() override
{
102 profile_manager_
.reset(
103 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
104 ASSERT_TRUE(profile_manager_
->SetUp());
105 profile_
= profile_manager_
->CreateTestingProfile("test-user@example.com");
106 registry_
.reset(new Registry(profile_
));
107 fake_watcher_
.entry_path
= base::FilePath(FILE_PATH_LITERAL("/a/b/c"));
108 fake_watcher_
.recursive
= true;
109 fake_watcher_
.subscribers
[GURL(kTemporaryOrigin
)].origin
=
110 GURL(kTemporaryOrigin
);
111 fake_watcher_
.subscribers
[GURL(kTemporaryOrigin
)].persistent
= false;
112 fake_watcher_
.subscribers
[GURL(kPersistentOrigin
)].origin
=
113 GURL(kPersistentOrigin
);
114 fake_watcher_
.subscribers
[GURL(kPersistentOrigin
)].persistent
= true;
115 fake_watcher_
.last_tag
= "hello-world";
118 content::TestBrowserThreadBundle thread_bundle_
;
119 scoped_ptr
<TestingProfileManager
> profile_manager_
;
120 TestingProfile
* profile_
;
121 scoped_ptr
<RegistryInterface
> registry_
;
122 Watcher fake_watcher_
;
125 TEST_F(FileSystemProviderRegistryTest
, RestoreFileSystems
) {
126 // Create a fake entry in the preferences.
127 RememberFakeFileSystem(profile_
, kExtensionId
, kFileSystemId
, kDisplayName
,
128 true /* writable */, true /* supports_notify_tag */,
129 kOpenedFilesLimit
, fake_watcher_
);
131 scoped_ptr
<RegistryInterface::RestoredFileSystems
> restored_file_systems
=
132 registry_
->RestoreFileSystems(kExtensionId
);
134 ASSERT_EQ(1u, restored_file_systems
->size());
135 const RegistryInterface::RestoredFileSystem
& restored_file_system
=
136 restored_file_systems
->at(0);
137 EXPECT_EQ(kExtensionId
, restored_file_system
.extension_id
);
138 EXPECT_EQ(kFileSystemId
, restored_file_system
.options
.file_system_id
);
139 EXPECT_EQ(kDisplayName
, restored_file_system
.options
.display_name
);
140 EXPECT_TRUE(restored_file_system
.options
.writable
);
141 EXPECT_TRUE(restored_file_system
.options
.supports_notify_tag
);
142 EXPECT_EQ(kOpenedFilesLimit
, restored_file_system
.options
.opened_files_limit
);
144 ASSERT_EQ(1u, restored_file_system
.watchers
.size());
145 const auto& restored_watcher_it
= restored_file_system
.watchers
.find(
146 WatcherKey(fake_watcher_
.entry_path
, fake_watcher_
.recursive
));
147 ASSERT_NE(restored_file_system
.watchers
.end(), restored_watcher_it
);
149 EXPECT_EQ(fake_watcher_
.entry_path
, restored_watcher_it
->second
.entry_path
);
150 EXPECT_EQ(fake_watcher_
.recursive
, restored_watcher_it
->second
.recursive
);
151 EXPECT_EQ(fake_watcher_
.last_tag
, restored_watcher_it
->second
.last_tag
);
154 TEST_F(FileSystemProviderRegistryTest
, RememberFileSystem
) {
155 MountOptions
options(kFileSystemId
, kDisplayName
);
156 options
.writable
= true;
157 options
.supports_notify_tag
= true;
158 options
.opened_files_limit
= kOpenedFilesLimit
;
160 ProvidedFileSystemInfo
file_system_info(
161 kExtensionId
, options
, base::FilePath(FILE_PATH_LITERAL("/a/b/c")),
162 false /* configurable */, true /* watchable */, extensions::SOURCE_FILE
);
165 watchers
[WatcherKey(fake_watcher_
.entry_path
, fake_watcher_
.recursive
)] =
168 registry_
->RememberFileSystem(file_system_info
, watchers
);
170 syncable_prefs::TestingPrefServiceSyncable
* const pref_service
=
171 profile_
->GetTestingPrefService();
172 ASSERT_TRUE(pref_service
);
174 const base::DictionaryValue
* const extensions
=
175 pref_service
->GetDictionary(prefs::kFileSystemProviderMounted
);
176 ASSERT_TRUE(extensions
);
178 const base::DictionaryValue
* file_systems
= NULL
;
179 ASSERT_TRUE(extensions
->GetDictionaryWithoutPathExpansion(kExtensionId
,
181 EXPECT_EQ(1u, file_systems
->size());
183 const base::Value
* file_system_value
= NULL
;
184 const base::DictionaryValue
* file_system
= NULL
;
186 file_systems
->GetWithoutPathExpansion(kFileSystemId
, &file_system_value
));
187 ASSERT_TRUE(file_system_value
->GetAsDictionary(&file_system
));
189 std::string file_system_id
;
190 EXPECT_TRUE(file_system
->GetStringWithoutPathExpansion(kPrefKeyFileSystemId
,
192 EXPECT_EQ(kFileSystemId
, file_system_id
);
194 std::string display_name
;
195 EXPECT_TRUE(file_system
->GetStringWithoutPathExpansion(kPrefKeyDisplayName
,
197 EXPECT_EQ(kDisplayName
, display_name
);
199 bool writable
= false;
201 file_system
->GetBooleanWithoutPathExpansion(kPrefKeyWritable
, &writable
));
202 EXPECT_TRUE(writable
);
204 bool supports_notify_tag
= false;
205 EXPECT_TRUE(file_system
->GetBooleanWithoutPathExpansion(
206 kPrefKeySupportsNotifyTag
, &supports_notify_tag
));
207 EXPECT_TRUE(supports_notify_tag
);
209 int opened_files_limit
= 0;
210 EXPECT_TRUE(file_system
->GetIntegerWithoutPathExpansion(
211 kPrefKeyOpenedFilesLimit
, &opened_files_limit
));
212 EXPECT_EQ(kOpenedFilesLimit
, opened_files_limit
);
214 const base::DictionaryValue
* watchers_value
= NULL
;
215 ASSERT_TRUE(file_system
->GetDictionaryWithoutPathExpansion(kPrefKeyWatchers
,
218 const base::DictionaryValue
* watcher
= NULL
;
219 ASSERT_TRUE(watchers_value
->GetDictionaryWithoutPathExpansion(
220 fake_watcher_
.entry_path
.value(), &watcher
));
222 std::string entry_path
;
223 EXPECT_TRUE(watcher
->GetStringWithoutPathExpansion(kPrefKeyWatcherEntryPath
,
225 EXPECT_EQ(fake_watcher_
.entry_path
.value(), entry_path
);
227 bool recursive
= false;
228 EXPECT_TRUE(watcher
->GetBooleanWithoutPathExpansion(kPrefKeyWatcherRecursive
,
230 EXPECT_EQ(fake_watcher_
.recursive
, recursive
);
232 std::string last_tag
;
233 EXPECT_TRUE(watcher
->GetStringWithoutPathExpansion(kPrefKeyWatcherLastTag
,
235 EXPECT_EQ(fake_watcher_
.last_tag
, last_tag
);
237 const base::ListValue
* persistent_origins
= NULL
;
238 ASSERT_TRUE(watcher
->GetListWithoutPathExpansion(
239 kPrefKeyWatcherPersistentOrigins
, &persistent_origins
));
240 ASSERT_GT(fake_watcher_
.subscribers
.size(), persistent_origins
->GetSize());
241 ASSERT_EQ(1u, persistent_origins
->GetSize());
242 std::string persistent_origin
;
243 EXPECT_TRUE(persistent_origins
->GetString(0, &persistent_origin
));
244 const auto& fake_subscriber_it
=
245 fake_watcher_
.subscribers
.find(GURL(persistent_origin
));
246 ASSERT_NE(fake_watcher_
.subscribers
.end(), fake_subscriber_it
);
247 EXPECT_TRUE(fake_subscriber_it
->second
.persistent
);
250 TEST_F(FileSystemProviderRegistryTest
, ForgetFileSystem
) {
251 // Create a fake file systems in the preferences.
252 RememberFakeFileSystem(profile_
, kExtensionId
, kFileSystemId
, kDisplayName
,
253 true /* writable */, true /* supports_notify_tag */,
254 kOpenedFilesLimit
, fake_watcher_
);
256 registry_
->ForgetFileSystem(kExtensionId
, kFileSystemId
);
258 syncable_prefs::TestingPrefServiceSyncable
* const pref_service
=
259 profile_
->GetTestingPrefService();
260 ASSERT_TRUE(pref_service
);
262 const base::DictionaryValue
* const extensions
=
263 pref_service
->GetDictionary(prefs::kFileSystemProviderMounted
);
264 ASSERT_TRUE(extensions
);
266 const base::DictionaryValue
* file_systems
= NULL
;
267 EXPECT_FALSE(extensions
->GetDictionaryWithoutPathExpansion(kExtensionId
,
271 TEST_F(FileSystemProviderRegistryTest
, UpdateWatcherTag
) {
272 MountOptions
options(kFileSystemId
, kDisplayName
);
273 options
.writable
= true;
274 options
.supports_notify_tag
= true;
276 ProvidedFileSystemInfo
file_system_info(
277 kExtensionId
, options
, base::FilePath(FILE_PATH_LITERAL("/a/b/c")),
278 false /* configurable */, true /* watchable */, extensions::SOURCE_FILE
);
281 watchers
[WatcherKey(fake_watcher_
.entry_path
, fake_watcher_
.recursive
)] =
284 registry_
->RememberFileSystem(file_system_info
, watchers
);
286 fake_watcher_
.last_tag
= "updated-tag";
287 registry_
->UpdateWatcherTag(file_system_info
, fake_watcher_
);
289 syncable_prefs::TestingPrefServiceSyncable
* const pref_service
=
290 profile_
->GetTestingPrefService();
291 ASSERT_TRUE(pref_service
);
293 const base::DictionaryValue
* const extensions
=
294 pref_service
->GetDictionary(prefs::kFileSystemProviderMounted
);
295 ASSERT_TRUE(extensions
);
297 const base::DictionaryValue
* file_systems
= NULL
;
298 ASSERT_TRUE(extensions
->GetDictionaryWithoutPathExpansion(kExtensionId
,
300 EXPECT_EQ(1u, file_systems
->size());
302 const base::Value
* file_system_value
= NULL
;
303 const base::DictionaryValue
* file_system
= NULL
;
305 file_systems
->GetWithoutPathExpansion(kFileSystemId
, &file_system_value
));
306 ASSERT_TRUE(file_system_value
->GetAsDictionary(&file_system
));
308 const base::DictionaryValue
* watchers_value
= NULL
;
309 ASSERT_TRUE(file_system
->GetDictionaryWithoutPathExpansion(kPrefKeyWatchers
,
312 const base::DictionaryValue
* watcher
= NULL
;
313 ASSERT_TRUE(watchers_value
->GetDictionaryWithoutPathExpansion(
314 fake_watcher_
.entry_path
.value(), &watcher
));
316 std::string last_tag
;
317 EXPECT_TRUE(watcher
->GetStringWithoutPathExpansion(kPrefKeyWatcherLastTag
,
319 EXPECT_EQ(fake_watcher_
.last_tag
, last_tag
);
322 } // namespace file_system_provider
323 } // namespace chromeos