Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / file_system_provider / service_unittest.cc
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/service.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/files/file.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h"
15 #include "chrome/browser/chromeos/file_system_provider/mount_path_util.h"
16 #include "chrome/browser/chromeos/file_system_provider/observer.h"
17 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_info.h"
18 #include "chrome/browser/chromeos/login/users/fake_user_manager.h"
19 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
20 #include "chrome/common/pref_names.h"
21 #include "chrome/test/base/testing_pref_service_syncable.h"
22 #include "chrome/test/base/testing_profile.h"
23 #include "components/user_prefs/user_prefs.h"
24 #include "content/public/test/test_browser_thread_bundle.h"
25 #include "extensions/browser/extension_registry.h"
26 #include "extensions/common/extension.h"
27 #include "extensions/common/manifest_constants.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "webkit/browser/fileapi/external_mount_points.h"
30
31 namespace chromeos {
32 namespace file_system_provider {
33 namespace {
34
35 const char kExtensionId[] = "mbflcebpggnecokmikipoihdbecnjfoj";
36 const char kDisplayName[] = "Camera Pictures";
37
38 // The dot in the file system ID is there in order to check that saving to
39 // preferences works correctly. File System ID is used as a key in
40 // a base::DictionaryValue, so it has to be stored without path expansion.
41 const char kFileSystemId[] = "camera/pictures/id .!@#$%^&*()_+";
42
43 // Utility observer, logging events from file_system_provider::Service.
44 class LoggingObserver : public Observer {
45  public:
46   class Event {
47    public:
48     Event(const ProvidedFileSystemInfo& file_system_info,
49           base::File::Error error)
50         : file_system_info_(file_system_info), error_(error) {}
51     ~Event() {}
52
53     const ProvidedFileSystemInfo& file_system_info() {
54       return file_system_info_;
55     }
56     base::File::Error error() { return error_; }
57
58    private:
59     ProvidedFileSystemInfo file_system_info_;
60     base::File::Error error_;
61   };
62
63   LoggingObserver() {}
64   virtual ~LoggingObserver() {}
65
66   // file_system_provider::Observer overrides.
67   virtual void OnProvidedFileSystemMount(
68       const ProvidedFileSystemInfo& file_system_info,
69       base::File::Error error) OVERRIDE {
70     mounts.push_back(Event(file_system_info, error));
71   }
72
73   virtual void OnProvidedFileSystemUnmount(
74       const ProvidedFileSystemInfo& file_system_info,
75       base::File::Error error) OVERRIDE {
76     unmounts.push_back(Event(file_system_info, error));
77   }
78
79   std::vector<Event> mounts;
80   std::vector<Event> unmounts;
81 };
82
83 // Creates a fake extension with the specified |extension_id|.
84 scoped_refptr<extensions::Extension> createFakeExtension(
85     const std::string& extension_id) {
86   base::DictionaryValue manifest;
87   std::string error;
88   manifest.SetStringWithoutPathExpansion(extensions::manifest_keys::kVersion,
89                                          "1.0.0.0");
90   manifest.SetStringWithoutPathExpansion(extensions::manifest_keys::kName,
91                                          "unused");
92   return extensions::Extension::Create(base::FilePath(),
93                                        extensions::Manifest::UNPACKED,
94                                        manifest,
95                                        extensions::Extension::NO_FLAGS,
96                                        extension_id,
97                                        &error);
98 }
99
100 // Stores a provided file system information in preferences.
101 void RememberFakeFileSystem(TestingProfile* profile,
102                             const std::string& extension_id,
103                             const std::string& file_system_id,
104                             const std::string& display_name,
105                             bool writable) {
106   TestingPrefServiceSyncable* const pref_service =
107       profile->GetTestingPrefService();
108   ASSERT_TRUE(pref_service);
109
110   base::DictionaryValue extensions;
111   base::DictionaryValue* file_systems = new base::DictionaryValue();
112   base::DictionaryValue* file_system = new base::DictionaryValue();
113   file_system->SetStringWithoutPathExpansion(kPrefKeyFileSystemId,
114                                              kFileSystemId);
115   file_system->SetStringWithoutPathExpansion(kPrefKeyDisplayName, kDisplayName);
116   file_system->SetBooleanWithoutPathExpansion(kPrefKeyWritable, writable);
117   file_systems->SetWithoutPathExpansion(kFileSystemId, file_system);
118   extensions.SetWithoutPathExpansion(kExtensionId, file_systems);
119
120   pref_service->Set(prefs::kFileSystemProviderMounted, extensions);
121 }
122
123 }  // namespace
124
125 class FileSystemProviderServiceTest : public testing::Test {
126  protected:
127   FileSystemProviderServiceTest() {}
128   virtual ~FileSystemProviderServiceTest() {}
129
130   virtual void SetUp() OVERRIDE {
131     profile_.reset(new TestingProfile);
132     user_manager_ = new FakeUserManager();
133     user_manager_->AddUser(profile_->GetProfileName());
134     user_manager_enabler_.reset(new ScopedUserManagerEnabler(user_manager_));
135     extension_registry_.reset(
136         new extensions::ExtensionRegistry(profile_.get()));
137     service_.reset(new Service(profile_.get(), extension_registry_.get()));
138     service_->SetFileSystemFactoryForTesting(
139         base::Bind(&FakeProvidedFileSystem::Create));
140     extension_ = createFakeExtension(kExtensionId);
141   }
142
143   content::TestBrowserThreadBundle thread_bundle_;
144   scoped_ptr<TestingProfile> profile_;
145   FakeUserManager* user_manager_;
146   scoped_ptr<ScopedUserManagerEnabler> user_manager_enabler_;
147   scoped_ptr<extensions::ExtensionRegistry> extension_registry_;
148   scoped_ptr<Service> service_;
149   scoped_refptr<extensions::Extension> extension_;
150 };
151
152 TEST_F(FileSystemProviderServiceTest, MountFileSystem) {
153   LoggingObserver observer;
154   service_->AddObserver(&observer);
155
156   EXPECT_TRUE(service_->MountFileSystem(
157       kExtensionId, kFileSystemId, kDisplayName, false /* writable */));
158
159   ASSERT_EQ(1u, observer.mounts.size());
160   EXPECT_EQ(kExtensionId, observer.mounts[0].file_system_info().extension_id());
161   EXPECT_EQ(kFileSystemId,
162             observer.mounts[0].file_system_info().file_system_id());
163   base::FilePath expected_mount_path =
164       util::GetMountPath(profile_.get(), kExtensionId, kFileSystemId);
165   EXPECT_EQ(expected_mount_path.AsUTF8Unsafe(),
166             observer.mounts[0].file_system_info().mount_path().AsUTF8Unsafe());
167   EXPECT_EQ(kDisplayName, observer.mounts[0].file_system_info().display_name());
168   EXPECT_FALSE(observer.mounts[0].file_system_info().writable());
169   EXPECT_EQ(base::File::FILE_OK, observer.mounts[0].error());
170   ASSERT_EQ(0u, observer.unmounts.size());
171
172   std::vector<ProvidedFileSystemInfo> file_system_info_list =
173       service_->GetProvidedFileSystemInfoList();
174   ASSERT_EQ(1u, file_system_info_list.size());
175
176   service_->RemoveObserver(&observer);
177 }
178
179 TEST_F(FileSystemProviderServiceTest, MountFileSystem_Writable) {
180   LoggingObserver observer;
181   service_->AddObserver(&observer);
182
183   EXPECT_TRUE(service_->MountFileSystem(
184       kExtensionId, kFileSystemId, kDisplayName, true /* writable */));
185
186   ASSERT_EQ(1u, observer.mounts.size());
187   EXPECT_TRUE(observer.mounts[0].file_system_info().writable());
188   ASSERT_EQ(0u, observer.unmounts.size());
189   std::vector<ProvidedFileSystemInfo> file_system_info_list =
190       service_->GetProvidedFileSystemInfoList();
191   ASSERT_EQ(1u, file_system_info_list.size());
192
193   service_->RemoveObserver(&observer);
194 }
195
196 TEST_F(FileSystemProviderServiceTest, MountFileSystem_UniqueIds) {
197   LoggingObserver observer;
198   service_->AddObserver(&observer);
199
200   EXPECT_TRUE(service_->MountFileSystem(
201       kExtensionId, kFileSystemId, kDisplayName, false /* writable */));
202   EXPECT_FALSE(service_->MountFileSystem(
203       kExtensionId, kFileSystemId, kDisplayName, false /* writable */));
204
205   ASSERT_EQ(2u, observer.mounts.size());
206   EXPECT_EQ(base::File::FILE_OK, observer.mounts[0].error());
207   EXPECT_EQ(base::File::FILE_ERROR_EXISTS, observer.mounts[1].error());
208
209   std::vector<ProvidedFileSystemInfo> file_system_info_list =
210       service_->GetProvidedFileSystemInfoList();
211   ASSERT_EQ(1u, file_system_info_list.size());
212
213   service_->RemoveObserver(&observer);
214 }
215
216 TEST_F(FileSystemProviderServiceTest, MountFileSystem_StressTest) {
217   LoggingObserver observer;
218   service_->AddObserver(&observer);
219
220   const size_t kMaxFileSystems = 16;
221   for (size_t i = 0; i < kMaxFileSystems; ++i) {
222     const std::string file_system_id =
223         std::string("test-") + base::IntToString(i);
224     EXPECT_TRUE(service_->MountFileSystem(
225         kExtensionId, file_system_id, kDisplayName, false /* writable */));
226   }
227   ASSERT_EQ(kMaxFileSystems, observer.mounts.size());
228
229   // The next file system is out of limit, and registering it should fail.
230   EXPECT_FALSE(service_->MountFileSystem(
231       kExtensionId, kFileSystemId, kDisplayName, false /* writable */));
232
233   ASSERT_EQ(kMaxFileSystems + 1, observer.mounts.size());
234   EXPECT_EQ(base::File::FILE_ERROR_TOO_MANY_OPENED,
235             observer.mounts[kMaxFileSystems].error());
236
237   std::vector<ProvidedFileSystemInfo> file_system_info_list =
238       service_->GetProvidedFileSystemInfoList();
239   ASSERT_EQ(kMaxFileSystems, file_system_info_list.size());
240
241   service_->RemoveObserver(&observer);
242 }
243
244 TEST_F(FileSystemProviderServiceTest, UnmountFileSystem) {
245   LoggingObserver observer;
246   service_->AddObserver(&observer);
247
248   EXPECT_TRUE(service_->MountFileSystem(
249       kExtensionId, kFileSystemId, kDisplayName, false /* writable */));
250   ASSERT_EQ(1u, observer.mounts.size());
251
252   EXPECT_TRUE(service_->UnmountFileSystem(
253       kExtensionId, kFileSystemId, Service::UNMOUNT_REASON_USER));
254   ASSERT_EQ(1u, observer.unmounts.size());
255   EXPECT_EQ(base::File::FILE_OK, observer.unmounts[0].error());
256
257   EXPECT_EQ(kExtensionId,
258             observer.unmounts[0].file_system_info().extension_id());
259   EXPECT_EQ(kFileSystemId,
260             observer.unmounts[0].file_system_info().file_system_id());
261
262   std::vector<ProvidedFileSystemInfo> file_system_info_list =
263       service_->GetProvidedFileSystemInfoList();
264   ASSERT_EQ(0u, file_system_info_list.size());
265
266   service_->RemoveObserver(&observer);
267 }
268
269 TEST_F(FileSystemProviderServiceTest, UnmountFileSystem_OnExtensionUnload) {
270   LoggingObserver observer;
271   service_->AddObserver(&observer);
272
273   EXPECT_TRUE(service_->MountFileSystem(
274       kExtensionId, kFileSystemId, kDisplayName, false /* writable */));
275   ASSERT_EQ(1u, observer.mounts.size());
276
277   // Directly call the observer's method.
278   service_->OnExtensionUnloaded(
279       profile_.get(),
280       extension_.get(),
281       extensions::UnloadedExtensionInfo::REASON_DISABLE);
282
283   ASSERT_EQ(1u, observer.unmounts.size());
284   EXPECT_EQ(base::File::FILE_OK, observer.unmounts[0].error());
285
286   EXPECT_EQ(kExtensionId,
287             observer.unmounts[0].file_system_info().extension_id());
288   EXPECT_EQ(kFileSystemId,
289             observer.unmounts[0].file_system_info().file_system_id());
290
291   std::vector<ProvidedFileSystemInfo> file_system_info_list =
292       service_->GetProvidedFileSystemInfoList();
293   ASSERT_EQ(0u, file_system_info_list.size());
294
295   service_->RemoveObserver(&observer);
296 }
297
298 TEST_F(FileSystemProviderServiceTest, UnmountFileSystem_WrongExtensionId) {
299   LoggingObserver observer;
300   service_->AddObserver(&observer);
301
302   const std::string kWrongExtensionId = "helloworldhelloworldhelloworldhe";
303
304   EXPECT_TRUE(service_->MountFileSystem(
305       kExtensionId, kFileSystemId, kDisplayName, false /* writable */));
306   ASSERT_EQ(1u, observer.mounts.size());
307   ASSERT_EQ(1u, service_->GetProvidedFileSystemInfoList().size());
308
309   EXPECT_FALSE(service_->UnmountFileSystem(
310       kWrongExtensionId, kFileSystemId, Service::UNMOUNT_REASON_USER));
311   ASSERT_EQ(1u, observer.unmounts.size());
312   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, observer.unmounts[0].error());
313   ASSERT_EQ(1u, service_->GetProvidedFileSystemInfoList().size());
314
315   std::vector<ProvidedFileSystemInfo> file_system_info_list =
316       service_->GetProvidedFileSystemInfoList();
317   ASSERT_EQ(1u, file_system_info_list.size());
318
319   service_->RemoveObserver(&observer);
320 }
321
322 TEST_F(FileSystemProviderServiceTest, RestoreFileSystem_OnExtensionLoad) {
323   // Create a fake entry in the preferences.
324   RememberFakeFileSystem(profile_.get(),
325                          kExtensionId,
326                          kFileSystemId,
327                          kDisplayName,
328                          true /* writable */);
329
330   // Create a new service instance in order to load remembered file systems
331   // from preferences.
332   scoped_ptr<Service> new_service(
333       new Service(profile_.get(), extension_registry_.get()));
334   LoggingObserver observer;
335   new_service->AddObserver(&observer);
336
337   new_service->SetFileSystemFactoryForTesting(
338       base::Bind(&FakeProvidedFileSystem::Create));
339
340   EXPECT_EQ(0u, observer.mounts.size());
341
342   // Directly call the observer's method.
343   new_service->OnExtensionLoaded(profile_.get(), extension_.get());
344
345   ASSERT_EQ(1u, observer.mounts.size());
346   EXPECT_EQ(base::File::FILE_OK, observer.mounts[0].error());
347
348   EXPECT_EQ(kExtensionId, observer.mounts[0].file_system_info().extension_id());
349   EXPECT_EQ(kFileSystemId,
350             observer.mounts[0].file_system_info().file_system_id());
351   EXPECT_TRUE(observer.mounts[0].file_system_info().writable());
352
353   std::vector<ProvidedFileSystemInfo> file_system_info_list =
354       new_service->GetProvidedFileSystemInfoList();
355   ASSERT_EQ(1u, file_system_info_list.size());
356
357   new_service->RemoveObserver(&observer);
358 }
359
360 TEST_F(FileSystemProviderServiceTest, RememberFileSystem_OnMount) {
361   LoggingObserver observer;
362   service_->AddObserver(&observer);
363
364   EXPECT_TRUE(service_->MountFileSystem(
365       kExtensionId, kFileSystemId, kDisplayName, true /* writable */));
366   ASSERT_EQ(1u, observer.mounts.size());
367
368   TestingPrefServiceSyncable* const pref_service =
369       profile_->GetTestingPrefService();
370   ASSERT_TRUE(pref_service);
371
372   const base::DictionaryValue* const extensions =
373       pref_service->GetDictionary(prefs::kFileSystemProviderMounted);
374   ASSERT_TRUE(extensions);
375
376   const base::DictionaryValue* file_systems = NULL;
377   ASSERT_TRUE(extensions->GetDictionaryWithoutPathExpansion(kExtensionId,
378                                                             &file_systems));
379   EXPECT_EQ(1u, file_systems->size());
380
381   const base::Value* file_system_value = NULL;
382   const base::DictionaryValue* file_system = NULL;
383   ASSERT_TRUE(
384       file_systems->GetWithoutPathExpansion(kFileSystemId, &file_system_value));
385   ASSERT_TRUE(file_system_value->GetAsDictionary(&file_system));
386
387   std::string file_system_id;
388   EXPECT_TRUE(file_system->GetStringWithoutPathExpansion(kPrefKeyFileSystemId,
389                                                          &file_system_id));
390   EXPECT_EQ(kFileSystemId, file_system_id);
391
392   std::string display_name;
393   EXPECT_TRUE(file_system->GetStringWithoutPathExpansion(kPrefKeyDisplayName,
394                                                          &display_name));
395   EXPECT_EQ(kDisplayName, display_name);
396
397   bool writable = false;
398   EXPECT_TRUE(
399       file_system->GetBooleanWithoutPathExpansion(kPrefKeyWritable, &writable));
400   EXPECT_TRUE(writable);
401
402   service_->RemoveObserver(&observer);
403 }
404
405 TEST_F(FileSystemProviderServiceTest, RememberFileSystem_OnUnmountOnShutdown) {
406   LoggingObserver observer;
407   service_->AddObserver(&observer);
408
409   TestingPrefServiceSyncable* const pref_service =
410       profile_->GetTestingPrefService();
411   ASSERT_TRUE(pref_service);
412
413   {
414     EXPECT_TRUE(service_->MountFileSystem(
415         kExtensionId, kFileSystemId, kDisplayName, false /* writable */));
416     ASSERT_EQ(1u, observer.mounts.size());
417
418     const base::DictionaryValue* extensions =
419         pref_service->GetDictionary(prefs::kFileSystemProviderMounted);
420     ASSERT_TRUE(extensions);
421
422     const base::DictionaryValue* file_systems = NULL;
423     ASSERT_TRUE(extensions->GetDictionaryWithoutPathExpansion(kExtensionId,
424                                                               &file_systems));
425     EXPECT_EQ(1u, file_systems->size());
426   }
427
428   {
429     EXPECT_TRUE(service_->UnmountFileSystem(
430         kExtensionId, kFileSystemId, Service::UNMOUNT_REASON_SHUTDOWN));
431
432     const base::DictionaryValue* const extensions =
433         pref_service->GetDictionary(prefs::kFileSystemProviderMounted);
434     ASSERT_TRUE(extensions);
435
436     const base::DictionaryValue* file_systems = NULL;
437     ASSERT_TRUE(extensions->GetDictionaryWithoutPathExpansion(kExtensionId,
438                                                               &file_systems));
439     EXPECT_EQ(1u, file_systems->size());
440   }
441
442   service_->RemoveObserver(&observer);
443 }
444
445 TEST_F(FileSystemProviderServiceTest, RememberFileSystem_OnUnmountByUser) {
446   LoggingObserver observer;
447   service_->AddObserver(&observer);
448
449   TestingPrefServiceSyncable* const pref_service =
450       profile_->GetTestingPrefService();
451   ASSERT_TRUE(pref_service);
452
453   {
454     EXPECT_TRUE(service_->MountFileSystem(
455         kExtensionId, kFileSystemId, kDisplayName, false /* writable */));
456     ASSERT_EQ(1u, observer.mounts.size());
457
458     const base::DictionaryValue* extensions =
459         pref_service->GetDictionary(prefs::kFileSystemProviderMounted);
460     ASSERT_TRUE(extensions);
461
462     const base::DictionaryValue* file_systems = NULL;
463     ASSERT_TRUE(extensions->GetDictionaryWithoutPathExpansion(kExtensionId,
464                                                               &file_systems));
465     EXPECT_EQ(1u, file_systems->size());
466   }
467
468   {
469     EXPECT_TRUE(service_->UnmountFileSystem(
470         kExtensionId, kFileSystemId, Service::UNMOUNT_REASON_USER));
471
472     const base::DictionaryValue* const extensions =
473         pref_service->GetDictionary(prefs::kFileSystemProviderMounted);
474     ASSERT_TRUE(extensions);
475
476     const base::DictionaryValue* file_systems = NULL;
477     EXPECT_FALSE(extensions->GetDictionaryWithoutPathExpansion(kExtensionId,
478                                                                &file_systems));
479   }
480
481   service_->RemoveObserver(&observer);
482 }
483
484 }  // namespace file_system_provider
485 }  // namespace chromeos