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