1// Copyright 2013 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_manager/volume_manager.h"
6
7#include <string>
8#include <vector>
9
10#include "base/basictypes.h"
11#include "base/prefs/pref_service.h"
12#include "base/strings/utf_string_conversions.h"
13#include "chrome/browser/chromeos/file_manager/fake_disk_mount_manager.h"
14#include "chrome/browser/chromeos/file_manager/volume_manager_observer.h"
15#include "chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h"
16#include "chrome/browser/chromeos/file_system_provider/service.h"
17#include "chrome/common/pref_names.h"
18#include "chrome/test/base/testing_profile.h"
19#include "chromeos/dbus/fake_power_manager_client.h"
20#include "chromeos/disks/disk_mount_manager.h"
21#include "components/storage_monitor/storage_info.h"
22#include "content/public/test/test_browser_thread_bundle.h"
23#include "extensions/browser/extension_registry.h"
24#include "testing/gtest/include/gtest/gtest.h"
25
26namespace file_manager {
27namespace {
28
29class LoggingObserver : public VolumeManagerObserver {
30 public:
31  struct Event {
32    enum EventType {
33      DISK_ADDED,
34      DISK_REMOVED,
35      DEVICE_ADDED,
36      DEVICE_REMOVED,
37      VOLUME_MOUNTED,
38      VOLUME_UNMOUNTED,
39      FORMAT_STARTED,
40      FORMAT_COMPLETED,
41    } type;
42
43    // Available on DEVICE_ADDED, DEVICE_REMOVED, VOLUME_MOUNTED,
44    // VOLUME_UNMOUNTED, FORMAT_STARTED and FORMAT_COMPLETED.
45    std::string device_path;
46
47    // Available on DISK_ADDED.
48    bool mounting;
49
50    // Available on VOLUME_MOUNTED and VOLUME_UNMOUNTED.
51    chromeos::MountError mount_error;
52
53    // Available on FORMAT_STARTED and FORMAT_COMPLETED.
54    bool success;
55  };
56
57  LoggingObserver() {}
58  virtual ~LoggingObserver() {}
59
60  const std::vector<Event>& events() const { return events_; }
61
62  // VolumeManagerObserver overrides.
63  virtual void OnDiskAdded(const chromeos::disks::DiskMountManager::Disk& disk,
64                           bool mounting) OVERRIDE {
65    Event event;
66    event.type = Event::DISK_ADDED;
67    event.device_path = disk.device_path();  // Keep only device_path.
68    event.mounting = mounting;
69    events_.push_back(event);
70  }
71
72  virtual void OnDiskRemoved(
73      const chromeos::disks::DiskMountManager::Disk& disk) OVERRIDE {
74    Event event;
75    event.type = Event::DISK_REMOVED;
76    event.device_path = disk.device_path();  // Keep only device_path.
77    events_.push_back(event);
78  }
79
80  virtual void OnDeviceAdded(const std::string& device_path) OVERRIDE {
81    Event event;
82    event.type = Event::DEVICE_ADDED;
83    event.device_path = device_path;
84    events_.push_back(event);
85  }
86
87  virtual void OnDeviceRemoved(const std::string& device_path) OVERRIDE {
88    Event event;
89    event.type = Event::DEVICE_REMOVED;
90    event.device_path = device_path;
91    events_.push_back(event);
92  }
93
94  virtual void OnVolumeMounted(chromeos::MountError error_code,
95                               const VolumeInfo& volume_info) OVERRIDE {
96    Event event;
97    event.type = Event::VOLUME_MOUNTED;
98    event.device_path = volume_info.source_path.AsUTF8Unsafe();
99    event.mount_error = error_code;
100    events_.push_back(event);
101  }
102
103  virtual void OnVolumeUnmounted(chromeos::MountError error_code,
104                                 const VolumeInfo& volume_info) OVERRIDE {
105    Event event;
106    event.type = Event::VOLUME_UNMOUNTED;
107    event.device_path = volume_info.source_path.AsUTF8Unsafe();
108    event.mount_error = error_code;
109    events_.push_back(event);
110  }
111
112  virtual void OnFormatStarted(
113      const std::string& device_path, bool success) OVERRIDE {
114    Event event;
115    event.type = Event::FORMAT_STARTED;
116    event.device_path = device_path;
117    event.success = success;
118    events_.push_back(event);
119  }
120
121  virtual void OnFormatCompleted(
122      const std::string& device_path, bool success) OVERRIDE {
123    Event event;
124    event.type = Event::FORMAT_COMPLETED;
125    event.device_path = device_path;
126    event.success = success;
127    events_.push_back(event);
128  }
129
130 private:
131  std::vector<Event> events_;
132
133  DISALLOW_COPY_AND_ASSIGN(LoggingObserver);
134};
135
136}  // namespace
137
138class VolumeManagerTest : public testing::Test {
139 protected:
140  // Helper class that contains per-profile objects.
141  class ProfileEnvironment {
142   public:
143    ProfileEnvironment(chromeos::PowerManagerClient* power_manager_client,
144                       chromeos::disks::DiskMountManager* disk_manager)
145        : profile_(new TestingProfile),
146          extension_registry_(
147              new extensions::ExtensionRegistry(profile_.get())),
148          file_system_provider_service_(
149              new chromeos::file_system_provider::Service(
150                  profile_.get(),
151                  extension_registry_.get())),
152          volume_manager_(
153              new VolumeManager(profile_.get(),
154                                NULL,  // DriveIntegrationService
155                                power_manager_client,
156                                disk_manager,
157                                file_system_provider_service_.get())) {
158      file_system_provider_service_->SetFileSystemFactoryForTesting(base::Bind(
159          &chromeos::file_system_provider::FakeProvidedFileSystem::Create));
160    }
161
162    Profile* profile() const { return profile_.get(); }
163    VolumeManager* volume_manager() const { return volume_manager_.get(); }
164
165   private:
166    scoped_ptr<TestingProfile> profile_;
167    scoped_ptr<extensions::ExtensionRegistry> extension_registry_;
168    scoped_ptr<chromeos::file_system_provider::Service>
169        file_system_provider_service_;
170    scoped_ptr<VolumeManager> volume_manager_;
171  };
172
173  virtual void SetUp() OVERRIDE {
174    power_manager_client_.reset(new chromeos::FakePowerManagerClient);
175    disk_mount_manager_.reset(new FakeDiskMountManager);
176    main_profile_.reset(new ProfileEnvironment(power_manager_client_.get(),
177                                               disk_mount_manager_.get()));
178  }
179
180  Profile* profile() const { return main_profile_->profile(); }
181  VolumeManager* volume_manager() const {
182    return main_profile_->volume_manager();
183  }
184
185  content::TestBrowserThreadBundle thread_bundle_;
186  scoped_ptr<chromeos::FakePowerManagerClient> power_manager_client_;
187  scoped_ptr<FakeDiskMountManager> disk_mount_manager_;
188  scoped_ptr<ProfileEnvironment> main_profile_;
189};
190
191TEST_F(VolumeManagerTest, OnDriveFileSystemMountAndUnmount) {
192  LoggingObserver observer;
193  volume_manager()->AddObserver(&observer);
194
195  volume_manager()->OnFileSystemMounted();
196
197  ASSERT_EQ(1U, observer.events().size());
198  LoggingObserver::Event event = observer.events()[0];
199  EXPECT_EQ(LoggingObserver::Event::VOLUME_MOUNTED, event.type);
200  EXPECT_EQ(drive::util::GetDriveMountPointPath(profile()).AsUTF8Unsafe(),
201            event.device_path);
202  EXPECT_EQ(chromeos::MOUNT_ERROR_NONE, event.mount_error);
203
204  volume_manager()->OnFileSystemBeingUnmounted();
205
206  ASSERT_EQ(2U, observer.events().size());
207  event = observer.events()[1];
208  EXPECT_EQ(LoggingObserver::Event::VOLUME_UNMOUNTED, event.type);
209  EXPECT_EQ(drive::util::GetDriveMountPointPath(profile()).AsUTF8Unsafe(),
210            event.device_path);
211  EXPECT_EQ(chromeos::MOUNT_ERROR_NONE, event.mount_error);
212
213  volume_manager()->RemoveObserver(&observer);
214}
215
216TEST_F(VolumeManagerTest, OnDriveFileSystemUnmountWithoutMount) {
217  LoggingObserver observer;
218  volume_manager()->AddObserver(&observer);
219  volume_manager()->OnFileSystemBeingUnmounted();
220
221  // Unmount event for non-mounted volume is not reported.
222  ASSERT_EQ(0U, observer.events().size());
223  volume_manager()->RemoveObserver(&observer);
224}
225
226TEST_F(VolumeManagerTest, OnDiskEvent_Hidden) {
227  LoggingObserver observer;
228  volume_manager()->AddObserver(&observer);
229
230  const bool kIsHidden = true;
231  const chromeos::disks::DiskMountManager::Disk kDisk(
232      "device1", "", "", "", "", "", "", "", "", "", "", "",
233      chromeos::DEVICE_TYPE_UNKNOWN, 0, false, false, false, false, false,
234      kIsHidden);
235
236  volume_manager()->OnDiskEvent(
237      chromeos::disks::DiskMountManager::DISK_ADDED, &kDisk);
238  EXPECT_EQ(0U, observer.events().size());
239
240  volume_manager()->OnDiskEvent(
241      chromeos::disks::DiskMountManager::DISK_REMOVED, &kDisk);
242  EXPECT_EQ(0U, observer.events().size());
243
244  volume_manager()->OnDiskEvent(
245      chromeos::disks::DiskMountManager::DISK_CHANGED, &kDisk);
246  EXPECT_EQ(0U, observer.events().size());
247
248  volume_manager()->RemoveObserver(&observer);
249}
250
251TEST_F(VolumeManagerTest, OnDiskEvent_Added) {
252  // Enable external storage.
253  profile()->GetPrefs()->SetBoolean(prefs::kExternalStorageDisabled, false);
254
255  LoggingObserver observer;
256  volume_manager()->AddObserver(&observer);
257
258  const chromeos::disks::DiskMountManager::Disk kEmptyDevicePathDisk(
259      "",  // empty device path.
260      "", "", "", "", "", "", "", "", "", "", "",
261      chromeos::DEVICE_TYPE_UNKNOWN, 0, false, false, false, false, false,
262      false);
263  volume_manager()->OnDiskEvent(
264      chromeos::disks::DiskMountManager::DISK_ADDED, &kEmptyDevicePathDisk);
265  EXPECT_EQ(0U, observer.events().size());
266
267  const bool kHasMedia = true;
268  const chromeos::disks::DiskMountManager::Disk kMediaDisk(
269      "device1", "", "", "", "", "", "", "", "", "", "", "",
270      chromeos::DEVICE_TYPE_UNKNOWN, 0, false, false, kHasMedia, false, false,
271      false);
272  volume_manager()->OnDiskEvent(
273      chromeos::disks::DiskMountManager::DISK_ADDED, &kMediaDisk);
274  ASSERT_EQ(1U, observer.events().size());
275  const LoggingObserver::Event& event = observer.events()[0];
276  EXPECT_EQ(LoggingObserver::Event::DISK_ADDED, event.type);
277  EXPECT_EQ("device1", event.device_path);
278  EXPECT_TRUE(event.mounting);
279
280  ASSERT_EQ(1U, disk_mount_manager_->mount_requests().size());
281  const FakeDiskMountManager::MountRequest& mount_request =
282      disk_mount_manager_->mount_requests()[0];
283  EXPECT_EQ("device1", mount_request.source_path);
284  EXPECT_EQ("", mount_request.source_format);
285  EXPECT_EQ("", mount_request.mount_label);
286  EXPECT_EQ(chromeos::MOUNT_TYPE_DEVICE, mount_request.type);
287
288  volume_manager()->RemoveObserver(&observer);
289}
290
291TEST_F(VolumeManagerTest, OnDiskEvent_AddedNonMounting) {
292  // Enable external storage.
293  profile()->GetPrefs()->SetBoolean(prefs::kExternalStorageDisabled, false);
294
295  // Device which is already mounted.
296  {
297    LoggingObserver observer;
298    volume_manager()->AddObserver(&observer);
299
300    const bool kHasMedia = true;
301    const chromeos::disks::DiskMountManager::Disk kMountedMediaDisk(
302        "device1", "mounted", "", "", "", "", "", "", "", "", "", "",
303        chromeos::DEVICE_TYPE_UNKNOWN, 0, false, false,
304        kHasMedia, false, false, false);
305    volume_manager()->OnDiskEvent(
306        chromeos::disks::DiskMountManager::DISK_ADDED, &kMountedMediaDisk);
307    ASSERT_EQ(1U, observer.events().size());
308    const LoggingObserver::Event& event = observer.events()[0];
309    EXPECT_EQ(LoggingObserver::Event::DISK_ADDED, event.type);
310    EXPECT_EQ("device1", event.device_path);
311    EXPECT_FALSE(event.mounting);
312
313    ASSERT_EQ(0U, disk_mount_manager_->mount_requests().size());
314
315    volume_manager()->RemoveObserver(&observer);
316  }
317
318  // Device without media.
319  {
320    LoggingObserver observer;
321    volume_manager()->AddObserver(&observer);
322
323    const bool kWithoutMedia = false;
324    const chromeos::disks::DiskMountManager::Disk kNoMediaDisk(
325        "device1", "", "", "", "", "", "", "", "", "", "", "",
326        chromeos::DEVICE_TYPE_UNKNOWN, 0, false, false,
327        kWithoutMedia, false, false, false);
328    volume_manager()->OnDiskEvent(
329        chromeos::disks::DiskMountManager::DISK_ADDED, &kNoMediaDisk);
330    ASSERT_EQ(1U, observer.events().size());
331    const LoggingObserver::Event& event = observer.events()[0];
332    EXPECT_EQ(LoggingObserver::Event::DISK_ADDED, event.type);
333    EXPECT_EQ("device1", event.device_path);
334    EXPECT_FALSE(event.mounting);
335
336    ASSERT_EQ(0U, disk_mount_manager_->mount_requests().size());
337
338    volume_manager()->RemoveObserver(&observer);
339  }
340
341  // External storage is disabled.
342  {
343    profile()->GetPrefs()->SetBoolean(prefs::kExternalStorageDisabled, true);
344
345    LoggingObserver observer;
346    volume_manager()->AddObserver(&observer);
347
348    const bool kHasMedia = true;
349    const chromeos::disks::DiskMountManager::Disk kMediaDisk(
350        "device1", "", "", "", "", "", "", "", "", "", "", "",
351        chromeos::DEVICE_TYPE_UNKNOWN, 0, false, false,
352        kHasMedia, false, false, false);
353    volume_manager()->OnDiskEvent(
354        chromeos::disks::DiskMountManager::DISK_ADDED, &kMediaDisk);
355    ASSERT_EQ(1U, observer.events().size());
356    const LoggingObserver::Event& event = observer.events()[0];
357    EXPECT_EQ(LoggingObserver::Event::DISK_ADDED, event.type);
358    EXPECT_EQ("device1", event.device_path);
359    EXPECT_FALSE(event.mounting);
360
361    ASSERT_EQ(0U, disk_mount_manager_->mount_requests().size());
362
363    volume_manager()->RemoveObserver(&observer);
364  }
365}
366
367TEST_F(VolumeManagerTest, OnDiskEvent_Removed) {
368  LoggingObserver observer;
369  volume_manager()->AddObserver(&observer);
370
371  const chromeos::disks::DiskMountManager::Disk kMountedDisk(
372      "device1", "mount_path", "", "", "", "", "", "", "", "", "", "",
373      chromeos::DEVICE_TYPE_UNKNOWN, 0, false, false, false, false, false,
374      false);
375  volume_manager()->OnDiskEvent(
376      chromeos::disks::DiskMountManager::DISK_REMOVED, &kMountedDisk);
377
378  ASSERT_EQ(1U, observer.events().size());
379  const LoggingObserver::Event& event = observer.events()[0];
380  EXPECT_EQ(LoggingObserver::Event::DISK_REMOVED, event.type);
381  EXPECT_EQ("device1", event.device_path);
382
383  ASSERT_EQ(1U, disk_mount_manager_->unmount_requests().size());
384  const FakeDiskMountManager::UnmountRequest& unmount_request =
385      disk_mount_manager_->unmount_requests()[0];
386  EXPECT_EQ("mount_path", unmount_request.mount_path);
387  EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_LAZY, unmount_request.options);
388
389  volume_manager()->RemoveObserver(&observer);
390}
391
392TEST_F(VolumeManagerTest, OnDiskEvent_RemovedNotMounted) {
393  LoggingObserver observer;
394  volume_manager()->AddObserver(&observer);
395
396  const chromeos::disks::DiskMountManager::Disk kNotMountedDisk(
397      "device1", "", "", "", "", "", "", "", "", "", "", "",
398      chromeos::DEVICE_TYPE_UNKNOWN, 0, false, false, false, false, false,
399      false);
400  volume_manager()->OnDiskEvent(
401      chromeos::disks::DiskMountManager::DISK_REMOVED, &kNotMountedDisk);
402
403  ASSERT_EQ(1U, observer.events().size());
404  const LoggingObserver::Event& event = observer.events()[0];
405  EXPECT_EQ(LoggingObserver::Event::DISK_REMOVED, event.type);
406  EXPECT_EQ("device1", event.device_path);
407
408  ASSERT_EQ(0U, disk_mount_manager_->unmount_requests().size());
409
410  volume_manager()->RemoveObserver(&observer);
411}
412
413TEST_F(VolumeManagerTest, OnDiskEvent_Changed) {
414  // Changed event should cause mounting (if possible).
415  LoggingObserver observer;
416  volume_manager()->AddObserver(&observer);
417
418  const chromeos::disks::DiskMountManager::Disk kDisk(
419      "device1", "", "", "", "", "", "", "", "", "", "", "",
420      chromeos::DEVICE_TYPE_UNKNOWN, 0, false, false, true, false, false,
421      false);
422  volume_manager()->OnDiskEvent(
423      chromeos::disks::DiskMountManager::DISK_CHANGED, &kDisk);
424
425  EXPECT_EQ(1U, observer.events().size());
426  EXPECT_EQ(1U, disk_mount_manager_->mount_requests().size());
427  EXPECT_EQ(0U, disk_mount_manager_->unmount_requests().size());
428
429  volume_manager()->RemoveObserver(&observer);
430}
431
432TEST_F(VolumeManagerTest, OnDeviceEvent_Added) {
433  LoggingObserver observer;
434  volume_manager()->AddObserver(&observer);
435
436  volume_manager()->OnDeviceEvent(
437      chromeos::disks::DiskMountManager::DEVICE_ADDED, "device1");
438
439  ASSERT_EQ(1U, observer.events().size());
440  const LoggingObserver::Event& event = observer.events()[0];
441  EXPECT_EQ(LoggingObserver::Event::DEVICE_ADDED, event.type);
442  EXPECT_EQ("device1", event.device_path);
443
444  volume_manager()->RemoveObserver(&observer);
445}
446
447TEST_F(VolumeManagerTest, OnDeviceEvent_Removed) {
448  LoggingObserver observer;
449  volume_manager()->AddObserver(&observer);
450
451  volume_manager()->OnDeviceEvent(
452      chromeos::disks::DiskMountManager::DEVICE_REMOVED, "device1");
453
454  ASSERT_EQ(1U, observer.events().size());
455  const LoggingObserver::Event& event = observer.events()[0];
456  EXPECT_EQ(LoggingObserver::Event::DEVICE_REMOVED, event.type);
457  EXPECT_EQ("device1", event.device_path);
458
459  volume_manager()->RemoveObserver(&observer);
460}
461
462TEST_F(VolumeManagerTest, OnDeviceEvent_Scanned) {
463  LoggingObserver observer;
464  volume_manager()->AddObserver(&observer);
465
466  volume_manager()->OnDeviceEvent(
467      chromeos::disks::DiskMountManager::DEVICE_SCANNED, "device1");
468
469  // SCANNED event is just ignored.
470  EXPECT_EQ(0U, observer.events().size());
471
472  volume_manager()->RemoveObserver(&observer);
473}
474
475TEST_F(VolumeManagerTest, OnMountEvent_MountingAndUnmounting) {
476  LoggingObserver observer;
477  volume_manager()->AddObserver(&observer);
478
479  const chromeos::disks::DiskMountManager::MountPointInfo kMountPoint(
480      "device1",
481      "mount1",
482      chromeos::MOUNT_TYPE_DEVICE,
483      chromeos::disks::MOUNT_CONDITION_NONE);
484
485  volume_manager()->OnMountEvent(chromeos::disks::DiskMountManager::MOUNTING,
486                                chromeos::MOUNT_ERROR_NONE,
487                                kMountPoint);
488
489  ASSERT_EQ(1U, observer.events().size());
490  LoggingObserver::Event event = observer.events()[0];
491  EXPECT_EQ(LoggingObserver::Event::VOLUME_MOUNTED, event.type);
492  EXPECT_EQ("device1", event.device_path);
493  EXPECT_EQ(chromeos::MOUNT_ERROR_NONE, event.mount_error);
494
495  volume_manager()->OnMountEvent(chromeos::disks::DiskMountManager::UNMOUNTING,
496                                chromeos::MOUNT_ERROR_NONE,
497                                kMountPoint);
498
499  ASSERT_EQ(2U, observer.events().size());
500  event = observer.events()[1];
501  EXPECT_EQ(LoggingObserver::Event::VOLUME_UNMOUNTED, event.type);
502  EXPECT_EQ("device1", event.device_path);
503  EXPECT_EQ(chromeos::MOUNT_ERROR_NONE, event.mount_error);
504
505  volume_manager()->RemoveObserver(&observer);
506}
507
508TEST_F(VolumeManagerTest, OnMountEvent_Remounting) {
509  scoped_ptr<chromeos::disks::DiskMountManager::Disk> disk(
510      new chromeos::disks::DiskMountManager::Disk(
511          "device1", "", "", "", "", "", "", "", "", "", "uuid1", "",
512          chromeos::DEVICE_TYPE_UNKNOWN, 0,
513          false, false, false, false, false, false));
514  disk_mount_manager_->AddDiskForTest(disk.release());
515  disk_mount_manager_->MountPath(
516      "device1", "", "", chromeos::MOUNT_TYPE_DEVICE);
517
518  const chromeos::disks::DiskMountManager::MountPointInfo kMountPoint(
519      "device1",
520      "mount1",
521      chromeos::MOUNT_TYPE_DEVICE,
522      chromeos::disks::MOUNT_CONDITION_NONE);
523
524  volume_manager()->OnMountEvent(
525      chromeos::disks::DiskMountManager::MOUNTING,
526      chromeos::MOUNT_ERROR_NONE,
527      kMountPoint);
528
529  LoggingObserver observer;
530
531  // Emulate system suspend and then resume.
532  {
533    power_manager_client_->SendSuspendImminent();
534    power_manager_client_->SendSuspendDone();
535
536    // After resume, the device is unmounted and then mounted.
537    volume_manager()->OnMountEvent(
538        chromeos::disks::DiskMountManager::UNMOUNTING,
539        chromeos::MOUNT_ERROR_NONE,
540        kMountPoint);
541
542    // Observe what happened for the mount event.
543    volume_manager()->AddObserver(&observer);
544
545    volume_manager()->OnMountEvent(
546        chromeos::disks::DiskMountManager::MOUNTING,
547        chromeos::MOUNT_ERROR_NONE,
548        kMountPoint);
549  }
550
551  ASSERT_EQ(1U, observer.events().size());
552  const LoggingObserver::Event& event = observer.events()[0];
553  EXPECT_EQ(LoggingObserver::Event::VOLUME_MOUNTED, event.type);
554  EXPECT_EQ("device1", event.device_path);
555  EXPECT_EQ(chromeos::MOUNT_ERROR_NONE, event.mount_error);
556
557  volume_manager()->RemoveObserver(&observer);
558}
559
560TEST_F(VolumeManagerTest, OnMountEvent_UnmountingWithoutMounting) {
561  LoggingObserver observer;
562  volume_manager()->AddObserver(&observer);
563
564  const chromeos::disks::DiskMountManager::MountPointInfo kMountPoint(
565      "device1",
566      "mount1",
567      chromeos::MOUNT_TYPE_DEVICE,
568      chromeos::disks::MOUNT_CONDITION_NONE);
569
570  volume_manager()->OnMountEvent(chromeos::disks::DiskMountManager::UNMOUNTING,
571                                chromeos::MOUNT_ERROR_NONE,
572                                kMountPoint);
573
574  // Unmount event for a disk not mounted in this manager is not reported.
575  ASSERT_EQ(0U, observer.events().size());
576
577  volume_manager()->RemoveObserver(&observer);
578}
579
580TEST_F(VolumeManagerTest, OnFormatEvent_Started) {
581  LoggingObserver observer;
582  volume_manager()->AddObserver(&observer);
583
584  volume_manager()->OnFormatEvent(
585      chromeos::disks::DiskMountManager::FORMAT_STARTED,
586      chromeos::FORMAT_ERROR_NONE,
587      "device1");
588
589  ASSERT_EQ(1U, observer.events().size());
590  const LoggingObserver::Event& event = observer.events()[0];
591  EXPECT_EQ(LoggingObserver::Event::FORMAT_STARTED, event.type);
592  EXPECT_EQ("device1", event.device_path);
593  EXPECT_TRUE(event.success);
594
595  volume_manager()->RemoveObserver(&observer);
596}
597
598TEST_F(VolumeManagerTest, OnFormatEvent_StartFailed) {
599  LoggingObserver observer;
600  volume_manager()->AddObserver(&observer);
601
602  volume_manager()->OnFormatEvent(
603      chromeos::disks::DiskMountManager::FORMAT_STARTED,
604      chromeos::FORMAT_ERROR_UNKNOWN,
605      "device1");
606
607  ASSERT_EQ(1U, observer.events().size());
608  const LoggingObserver::Event& event = observer.events()[0];
609  EXPECT_EQ(LoggingObserver::Event::FORMAT_STARTED, event.type);
610  EXPECT_EQ("device1", event.device_path);
611  EXPECT_FALSE(event.success);
612
613  volume_manager()->RemoveObserver(&observer);
614}
615
616TEST_F(VolumeManagerTest, OnFormatEvent_Completed) {
617  LoggingObserver observer;
618  volume_manager()->AddObserver(&observer);
619
620  volume_manager()->OnFormatEvent(
621      chromeos::disks::DiskMountManager::FORMAT_COMPLETED,
622      chromeos::FORMAT_ERROR_NONE,
623      "device1");
624
625  ASSERT_EQ(1U, observer.events().size());
626  const LoggingObserver::Event& event = observer.events()[0];
627  EXPECT_EQ(LoggingObserver::Event::FORMAT_COMPLETED, event.type);
628  EXPECT_EQ("device1", event.device_path);
629  EXPECT_TRUE(event.success);
630
631  // When "format" is successfully done, VolumeManager requests to mount it.
632  ASSERT_EQ(1U, disk_mount_manager_->mount_requests().size());
633  const FakeDiskMountManager::MountRequest& mount_request =
634      disk_mount_manager_->mount_requests()[0];
635  EXPECT_EQ("device1", mount_request.source_path);
636  EXPECT_EQ("", mount_request.source_format);
637  EXPECT_EQ("", mount_request.mount_label);
638  EXPECT_EQ(chromeos::MOUNT_TYPE_DEVICE, mount_request.type);
639
640  volume_manager()->RemoveObserver(&observer);
641}
642
643TEST_F(VolumeManagerTest, OnFormatEvent_CompletedFailed) {
644  LoggingObserver observer;
645  volume_manager()->AddObserver(&observer);
646
647  volume_manager()->OnFormatEvent(
648      chromeos::disks::DiskMountManager::FORMAT_COMPLETED,
649      chromeos::FORMAT_ERROR_UNKNOWN,
650      "device1");
651
652  ASSERT_EQ(1U, observer.events().size());
653  const LoggingObserver::Event& event = observer.events()[0];
654  EXPECT_EQ(LoggingObserver::Event::FORMAT_COMPLETED, event.type);
655  EXPECT_EQ("device1", event.device_path);
656  EXPECT_FALSE(event.success);
657
658  EXPECT_EQ(0U, disk_mount_manager_->mount_requests().size());
659
660  volume_manager()->RemoveObserver(&observer);
661}
662
663TEST_F(VolumeManagerTest, OnExternalStorageDisabledChanged) {
664  // Here create two mount points.
665  disk_mount_manager_->MountPath(
666      "mount1", "", "", chromeos::MOUNT_TYPE_DEVICE);
667  disk_mount_manager_->MountPath(
668      "mount2", "", "", chromeos::MOUNT_TYPE_DEVICE);
669
670  // Initially, there are two mount points.
671  ASSERT_EQ(2U, disk_mount_manager_->mount_points().size());
672  ASSERT_EQ(0U, disk_mount_manager_->unmount_requests().size());
673
674  // Emulate to set kExternalStorageDisabled to false.
675  profile()->GetPrefs()->SetBoolean(prefs::kExternalStorageDisabled, false);
676  volume_manager()->OnExternalStorageDisabledChanged();
677
678  // Expect no effects.
679  EXPECT_EQ(2U, disk_mount_manager_->mount_points().size());
680  EXPECT_EQ(0U, disk_mount_manager_->unmount_requests().size());
681
682  // Emulate to set kExternalStorageDisabled to true.
683  profile()->GetPrefs()->SetBoolean(prefs::kExternalStorageDisabled, true);
684  volume_manager()->OnExternalStorageDisabledChanged();
685
686  // The all mount points should be unmounted.
687  EXPECT_EQ(0U, disk_mount_manager_->mount_points().size());
688
689  EXPECT_EQ(2U, disk_mount_manager_->unmount_requests().size());
690  const FakeDiskMountManager::UnmountRequest& unmount_request1 =
691      disk_mount_manager_->unmount_requests()[0];
692  EXPECT_EQ("mount1", unmount_request1.mount_path);
693
694  const FakeDiskMountManager::UnmountRequest& unmount_request2 =
695      disk_mount_manager_->unmount_requests()[1];
696  EXPECT_EQ("mount2", unmount_request2.mount_path);
697}
698
699TEST_F(VolumeManagerTest, ExternalStorageDisabledPolicyMultiProfile) {
700  ProfileEnvironment secondary(power_manager_client_.get(),
701                               disk_mount_manager_.get());
702  volume_manager()->Initialize();
703  secondary.volume_manager()->Initialize();
704
705  // Simulates the case that the main profile has kExternalStorageDisabled set
706  // as false, and the secondary profile has the config set to true.
707  profile()->GetPrefs()->SetBoolean(prefs::kExternalStorageDisabled, false);
708  secondary.profile()->GetPrefs()->SetBoolean(prefs::kExternalStorageDisabled,
709                                              true);
710
711  LoggingObserver main_observer, secondary_observer;
712  volume_manager()->AddObserver(&main_observer);
713  secondary.volume_manager()->AddObserver(&secondary_observer);
714
715  // Add 1 disk.
716  const chromeos::disks::DiskMountManager::Disk kMediaDisk(
717      "device1", "", "", "", "", "", "", "", "", "", "", "",
718      chromeos::DEVICE_TYPE_UNKNOWN, 0, false, false, true, false, false,
719      false);
720  volume_manager()->OnDiskEvent(
721      chromeos::disks::DiskMountManager::DISK_ADDED, &kMediaDisk);
722  secondary.volume_manager()->OnDiskEvent(
723      chromeos::disks::DiskMountManager::DISK_ADDED, &kMediaDisk);
724
725  // The profile with external storage enabled should have mounted the volume.
726  bool has_volume_mounted = false;
727  for (size_t i = 0; i < main_observer.events().size(); ++i) {
728    if (main_observer.events()[i].type ==
729        LoggingObserver::Event::VOLUME_MOUNTED)
730      has_volume_mounted = true;
731  }
732  EXPECT_TRUE(has_volume_mounted);
733
734  // The other profiles with external storage disabled should have not.
735  has_volume_mounted = false;
736  for (size_t i = 0; i < secondary_observer.events().size(); ++i) {
737    if (secondary_observer.events()[i].type ==
738        LoggingObserver::Event::VOLUME_MOUNTED)
739      has_volume_mounted = true;
740  }
741  EXPECT_FALSE(has_volume_mounted);
742
743  volume_manager()->RemoveObserver(&main_observer);
744  secondary.volume_manager()->RemoveObserver(&secondary_observer);
745}
746
747TEST_F(VolumeManagerTest, GetVolumeInfoList) {
748  volume_manager()->Initialize();  // Adds "Downloads"
749  std::vector<VolumeInfo> info_list = volume_manager()->GetVolumeInfoList();
750  ASSERT_EQ(1u, info_list.size());
751  EXPECT_EQ("downloads:Downloads", info_list[0].volume_id);
752  EXPECT_EQ(VOLUME_TYPE_DOWNLOADS_DIRECTORY, info_list[0].type);
753}
754
755TEST_F(VolumeManagerTest, FindVolumeInfoById) {
756  volume_manager()->Initialize();  // Adds "Downloads"
757  VolumeInfo volume_info;
758  ASSERT_FALSE(volume_manager()->FindVolumeInfoById(
759      "nonexistent", &volume_info));
760  ASSERT_TRUE(volume_manager()->FindVolumeInfoById(
761      "downloads:Downloads", &volume_info));
762  EXPECT_EQ("downloads:Downloads", volume_info.volume_id);
763  EXPECT_EQ(VOLUME_TYPE_DOWNLOADS_DIRECTORY, volume_info.type);
764}
765
766TEST_F(VolumeManagerTest, ArchiveSourceFiltering) {
767  LoggingObserver observer;
768  volume_manager()->AddObserver(&observer);
769
770  // Mount a USB stick.
771  volume_manager()->OnMountEvent(
772      chromeos::disks::DiskMountManager::MOUNTING,
773      chromeos::MOUNT_ERROR_NONE,
774      chromeos::disks::DiskMountManager::MountPointInfo(
775          "/removable/usb",
776          "/removable/usb",
777          chromeos::MOUNT_TYPE_DEVICE,
778          chromeos::disks::MOUNT_CONDITION_NONE));
779
780  // Mount a zip archive in the stick.
781  volume_manager()->OnMountEvent(
782      chromeos::disks::DiskMountManager::MOUNTING,
783      chromeos::MOUNT_ERROR_NONE,
784      chromeos::disks::DiskMountManager::MountPointInfo(
785          "/removable/usb/1.zip",
786          "/archive/1",
787          chromeos::MOUNT_TYPE_ARCHIVE,
788          chromeos::disks::MOUNT_CONDITION_NONE));
789  VolumeInfo volume_info;
790  ASSERT_TRUE(volume_manager()->FindVolumeInfoById("archive:1", &volume_info));
791  EXPECT_EQ("/archive/1", volume_info.mount_path.AsUTF8Unsafe());
792  EXPECT_EQ(2u, observer.events().size());
793
794  // Mount a zip archive in the previous zip archive.
795  volume_manager()->OnMountEvent(
796      chromeos::disks::DiskMountManager::MOUNTING,
797      chromeos::MOUNT_ERROR_NONE,
798      chromeos::disks::DiskMountManager::MountPointInfo(
799          "/archive/1/2.zip",
800          "/archive/2",
801          chromeos::MOUNT_TYPE_ARCHIVE,
802          chromeos::disks::MOUNT_CONDITION_NONE));
803  ASSERT_TRUE(volume_manager()->FindVolumeInfoById("archive:2", &volume_info));
804  EXPECT_EQ("/archive/2", volume_info.mount_path.AsUTF8Unsafe());
805  EXPECT_EQ(3u, observer.events().size());
806
807  // A zip file is mounted from other profile. It must be ignored in the current
808  // VolumeManager.
809  volume_manager()->OnMountEvent(
810      chromeos::disks::DiskMountManager::MOUNTING,
811      chromeos::MOUNT_ERROR_NONE,
812      chromeos::disks::DiskMountManager::MountPointInfo(
813          "/other/profile/drive/folder/3.zip",
814          "/archive/3",
815          chromeos::MOUNT_TYPE_ARCHIVE,
816          chromeos::disks::MOUNT_CONDITION_NONE));
817  EXPECT_FALSE(volume_manager()->FindVolumeInfoById("archive:3", &volume_info));
818  EXPECT_EQ(3u, observer.events().size());
819}
820
821TEST_F(VolumeManagerTest, MTPPlugAndUnplug) {
822  LoggingObserver observer;
823  volume_manager()->AddObserver(&observer);
824
825  storage_monitor::StorageInfo info(
826      storage_monitor::StorageInfo::MakeDeviceId(
827          storage_monitor::StorageInfo::MTP_OR_PTP, "dummy-device-id"),
828      FILE_PATH_LITERAL("/dummy/device/location"),
829      base::UTF8ToUTF16("label"),
830      base::UTF8ToUTF16("vendor"),
831      base::UTF8ToUTF16("model"),
832      12345 /* size */);
833
834  storage_monitor::StorageInfo non_mtp_info(
835      storage_monitor::StorageInfo::MakeDeviceId(
836          storage_monitor::StorageInfo::IPHOTO, "dummy-device-id2"),
837      FILE_PATH_LITERAL("/dummy/device/location2"),
838      base::UTF8ToUTF16("label2"),
839      base::UTF8ToUTF16("vendor2"),
840      base::UTF8ToUTF16("model2"),
841      12345 /* size */);
842
843  // Attach
844  volume_manager()->OnRemovableStorageAttached(info);
845  ASSERT_EQ(1u, observer.events().size());
846  EXPECT_EQ(LoggingObserver::Event::VOLUME_MOUNTED, observer.events()[0].type);
847
848  VolumeInfo volume_info;
849  ASSERT_TRUE(volume_manager()->FindVolumeInfoById("mtp:model", &volume_info));
850  EXPECT_EQ(VOLUME_TYPE_MTP, volume_info.type);
851
852  // Non MTP events from storage monitor are ignored.
853  volume_manager()->OnRemovableStorageAttached(non_mtp_info);
854  EXPECT_EQ(1u, observer.events().size());
855
856  // Detach
857  volume_manager()->OnRemovableStorageDetached(info);
858  ASSERT_EQ(2u, observer.events().size());
859  EXPECT_EQ(LoggingObserver::Event::VOLUME_UNMOUNTED,
860            observer.events()[1].type);
861
862  EXPECT_FALSE(volume_manager()->FindVolumeInfoById("mtp:model", &volume_info));
863}
864
865}  // namespace file_manager
866