1 // Copyright (c) 2012 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/system_monitor/removable_device_notifications_mac.h"
7 #include "base/file_util.h"
8 #include "base/mac/foundation_util.h"
9 #include "base/message_loop.h"
10 #include "base/scoped_temp_dir.h"
11 #include "base/sys_string_conversions.h"
12 #include "base/system_monitor/system_monitor.h"
13 #include "base/test/mock_devices_changed_observer.h"
14 #include "base/utf_string_conversions.h"
15 #include "chrome/browser/system_monitor/media_storage_util.h"
16 #include "chrome/browser/system_monitor/removable_device_constants.h"
17 #include "content/public/test/test_browser_thread.h"
18 #include "testing/gtest/include/gtest/gtest.h"
24 DiskInfoMac CreateDiskInfoMac(const std::string& unique_id,
25 const std::string& model_name,
26 const string16& display_name,
27 const FilePath& mount_point) {
28 NSMutableDictionary *dict = [NSMutableDictionary dictionary];
29 [dict setObject:@"dummy_bsd_name"
30 forKey:base::mac::CFToNSCast(kDADiskDescriptionMediaBSDNameKey)];
31 [dict setObject:base::SysUTF8ToNSString(unique_id)
32 forKey:base::mac::CFToNSCast(kDADiskDescriptionDeviceRevisionKey)];
33 if (!model_name.empty()) {
34 [dict setObject:base::SysUTF8ToNSString(model_name)
35 forKey:base::mac::CFToNSCast(kDADiskDescriptionDeviceModelKey)];
37 NSString* path = base::mac::FilePathToNSString(mount_point);
38 [dict setObject:[NSURL fileURLWithPath:path]
39 forKey:base::mac::CFToNSCast(kDADiskDescriptionVolumePathKey)];
40 [dict setObject:base::SysUTF16ToNSString(display_name)
41 forKey:base::mac::CFToNSCast(kDADiskDescriptionVolumeNameKey)];
42 [dict setObject:[NSNumber numberWithBool:YES]
43 forKey:base::mac::CFToNSCast(kDADiskDescriptionMediaRemovableKey)];
44 return DiskInfoMac::BuildDiskInfoOnFileThread(base::mac::NSToCFCast(dict));
49 class RemovableDeviceNotificationsMacTest : public testing::Test {
51 RemovableDeviceNotificationsMacTest()
52 : message_loop_(MessageLoop::TYPE_IO),
53 file_thread_(content::BrowserThread::FILE, &message_loop_) {
56 virtual void SetUp() OVERRIDE {
57 base::SystemMonitor::AllocateSystemIOPorts();
58 system_monitor_.reset(new base::SystemMonitor());
60 mock_devices_changed_observer_.reset(new base::MockDevicesChangedObserver);
61 system_monitor_->AddDevicesChangedObserver(
62 mock_devices_changed_observer_.get());
64 notifications_ = new RemovableDeviceNotificationsMac;
66 unique_id_ = "test_id";
67 display_name_ = ASCIIToUTF16("Test Display Name");
68 mount_point_ = FilePath("/unused_test_directory");
69 device_id_ = MediaStorageUtil::MakeDeviceId(
70 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM, unique_id_);
71 disk_info_ = CreateDiskInfoMac(unique_id_, "", display_name_, mount_point_);
75 // The message loop and file thread to run tests on.
76 MessageLoop message_loop_;
77 content::TestBrowserThread file_thread_;
79 // SystemMonitor and DevicesChangedObserver to hook together to test.
80 scoped_ptr<base::SystemMonitor> system_monitor_;
81 scoped_ptr<base::MockDevicesChangedObserver> mock_devices_changed_observer_;
83 // Information about the disk.
84 std::string unique_id_;
85 string16 display_name_;
86 FilePath mount_point_;
87 std::string device_id_;
88 DiskInfoMac disk_info_;
90 scoped_refptr<RemovableDeviceNotificationsMac> notifications_;
93 TEST_F(RemovableDeviceNotificationsMacTest, AddRemove) {
95 EXPECT_CALL(*mock_devices_changed_observer_,
96 OnRemovableStorageAttached(device_id_,
98 mount_point_.value()));
99 notifications_->UpdateDisk(
100 disk_info_, RemovableDeviceNotificationsMac::UPDATE_DEVICE_ADDED);
101 message_loop_.RunAllPending();
105 EXPECT_CALL(*mock_devices_changed_observer_,
106 OnRemovableStorageDetached(device_id_));
107 notifications_->UpdateDisk(
108 disk_info_, RemovableDeviceNotificationsMac::UPDATE_DEVICE_REMOVED);
109 message_loop_.RunAllPending();
113 TEST_F(RemovableDeviceNotificationsMacTest, UpdateVolumeName) {
115 EXPECT_CALL(*mock_devices_changed_observer_,
116 OnRemovableStorageAttached(device_id_,
118 mount_point_.value()));
119 notifications_->UpdateDisk(
120 disk_info_, RemovableDeviceNotificationsMac::UPDATE_DEVICE_ADDED);
121 message_loop_.RunAllPending();
125 string16 new_display_name(ASCIIToUTF16("Test Display Name"));
126 DiskInfoMac info2 = CreateDiskInfoMac(
127 unique_id_, "", new_display_name, mount_point_);
128 EXPECT_CALL(*mock_devices_changed_observer_,
129 OnRemovableStorageDetached(device_id_));
130 EXPECT_CALL(*mock_devices_changed_observer_,
131 OnRemovableStorageAttached(device_id_,
133 mount_point_.value()));
134 notifications_->UpdateDisk(
135 info2, RemovableDeviceNotificationsMac::UPDATE_DEVICE_CHANGED);
136 message_loop_.RunAllPending();
140 TEST_F(RemovableDeviceNotificationsMacTest, DCIM) {
141 ScopedTempDir temp_dir;
142 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
143 file_util::CreateDirectory(temp_dir.path().Append(kDCIMDirectoryName));
145 FilePath mount_point = temp_dir.path();
146 DiskInfoMac info = CreateDiskInfoMac(
147 unique_id_, "", display_name_, mount_point);
148 std::string device_id = MediaStorageUtil::MakeDeviceId(
149 MediaStorageUtil::REMOVABLE_MASS_STORAGE_WITH_DCIM, unique_id_);
152 EXPECT_CALL(*mock_devices_changed_observer_,
153 OnRemovableStorageAttached(device_id,
155 mount_point.value()));
156 notifications_->UpdateDisk(
157 info, RemovableDeviceNotificationsMac::UPDATE_DEVICE_ADDED);
158 message_loop_.RunAllPending();
162 TEST_F(RemovableDeviceNotificationsMacTest, GetDeviceInfo) {
164 EXPECT_CALL(*mock_devices_changed_observer_,
165 OnRemovableStorageAttached(device_id_,
167 mount_point_.value()));
168 notifications_->UpdateDisk(
169 disk_info_, RemovableDeviceNotificationsMac::UPDATE_DEVICE_ADDED);
170 message_loop_.RunAllPending();
173 base::SystemMonitor::RemovableStorageInfo info;
174 EXPECT_TRUE(notifications_->GetDeviceInfoForPath(
175 mount_point_.AppendASCII("foo"), &info));
176 EXPECT_EQ(info.device_id, device_id_);
177 EXPECT_EQ(info.name, display_name_);
178 EXPECT_EQ(info.location, mount_point_.value());
180 EXPECT_FALSE(notifications_->GetDeviceInfoForPath(
181 FilePath("/non/matching/path"), &info));
184 // Test that mounting a DMG doesn't send a notification.
185 TEST_F(RemovableDeviceNotificationsMacTest, DMG) {
186 EXPECT_CALL(*mock_devices_changed_observer_,
187 OnRemovableStorageAttached(testing::_,
189 testing::_)).Times(0);
190 DiskInfoMac info = CreateDiskInfoMac(
191 unique_id_, "Disk Image", display_name_, mount_point_);
192 notifications_->UpdateDisk(
193 info, RemovableDeviceNotificationsMac::UPDATE_DEVICE_ADDED);
194 message_loop_.RunAllPending();
197 } // namespace chrome