Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(574)

Side by Side Diff: chrome/browser/system_monitor/removable_device_notifications_mac.mm

Issue 10919185: Implement RemovableDeviceNotifications for Mac (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address review comments Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/system_monitor/removable_device_notifications_mac.h"
6
7 #include "content/public/browser/browser_thread.h"
8
9 namespace chrome {
10
11 namespace {
12
13 void GetDiskInfoAndUpdateOnFileThread(
14 const base::WeakPtr<RemovableDeviceNotificationsMac>& notifications,
15 base::mac::ScopedCFTypeRef<CFDictionaryRef> dict,
16 RemovableDeviceNotificationsMac::UpdateType update_type) {
17 DiskInfoMac info = DiskInfoMac::BuildDiskInfoOnFileThread(dict);
18 if (info.device_id().empty())
19 return;
20
21 content::BrowserThread::PostTask(
22 content::BrowserThread::UI,
23 FROM_HERE,
24 base::Bind(&RemovableDeviceNotificationsMac::UpdateDisk,
25 notifications,
26 info,
27 update_type));
28 }
29
30 void GetDiskInfoAndUpdate(
31 const base::WeakPtr<RemovableDeviceNotificationsMac>& notifications,
32 DADiskRef disk,
33 RemovableDeviceNotificationsMac::UpdateType update_type) {
34 base::mac::ScopedCFTypeRef<CFDictionaryRef> dict(DADiskCopyDescription(disk));
35 content::BrowserThread::PostTask(
36 content::BrowserThread::FILE,
37 FROM_HERE,
38 base::Bind(GetDiskInfoAndUpdateOnFileThread,
39 notifications,
40 dict,
41 update_type));
42 }
43
44 } // namespace
45
46 RemovableDeviceNotificationsMac::RemovableDeviceNotificationsMac() {
47 session_.reset(DASessionCreate(NULL));
48 DASessionScheduleWithRunLoop(
49 session_, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
50
51 // Register for callbacks for attached, changed, and removed devices.
52 // This will send notifications for existing devices too.
53 DARegisterDiskAppearedCallback(
54 session_,
55 kDADiskDescriptionMatchVolumeMountable,
56 DiskAppearedCallback,
57 this);
58 DARegisterDiskDisappearedCallback(
59 session_,
60 kDADiskDescriptionMatchVolumeMountable,
61 DiskDisappearedCallback,
62 this);
63 DARegisterDiskDescriptionChangedCallback(
64 session_,
65 kDADiskDescriptionMatchVolumeMountable,
66 kDADiskDescriptionWatchVolumePath,
67 DiskDescriptionChangedCallback,
68 this);
69 }
70
71 RemovableDeviceNotificationsMac::~RemovableDeviceNotificationsMac() {
72 DASessionUnscheduleFromRunLoop(
73 session_, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
74 }
75
76 void RemovableDeviceNotificationsMac::UpdateDisk(
77 const DiskInfoMac& info,
78 UpdateType update_type) {
79 if (info.bsd_name().empty())
80 return;
81
82 std::map<std::string, DiskInfoMac>::iterator it =
83 disk_info_map_.find(info.bsd_name());
84 if (it != disk_info_map_.end()) {
85 // If an attached notification was previously posted then post a detached
86 // notification now. This is used for devices that are being removed or
87 // devices that have changed.
88 if (ShouldPostNotificationForDisk(it->second)) {
89 base::SystemMonitor::Get()->ProcessRemovableStorageDetached(
90 it->second.device_id());
91 }
92 }
93
94 if (update_type == UPDATE_DEVICE_REMOVED) {
95 if (it != disk_info_map_.end())
96 disk_info_map_.erase(it);
97 } else {
98 disk_info_map_[info.bsd_name()] = info;
99 if (ShouldPostNotificationForDisk(info)) {
100 base::SystemMonitor::Get()->ProcessRemovableStorageAttached(
101 info.device_id(), info.display_name(), info.mount_point().value());
102 }
103 }
104 }
105
106 bool RemovableDeviceNotificationsMac::GetDeviceInfoForPath(
107 const FilePath& path,
108 base::SystemMonitor::RemovableStorageInfo* device_info) const {
109 if (!path.IsAbsolute())
110 return false;
111
112 FilePath current = path;
113 const FilePath root(FilePath::kSeparators);
114 while (current != root) {
115 DiskInfoMac info;
116 if (FindDiskWithMountPoint(current, &info)) {
117 device_info->device_id = info.device_id();
118 device_info->name = info.display_name();
119 device_info->location = info.mount_point().value();
120 return true;
121 }
122 current = current.DirName();
123 }
124
125 return false;
126 }
127
128 // static
129 void RemovableDeviceNotificationsMac::DiskAppearedCallback(
130 DADiskRef disk,
131 void* context) {
132 RemovableDeviceNotificationsMac* notifications =
133 static_cast<RemovableDeviceNotificationsMac*>(context);
134 GetDiskInfoAndUpdate(notifications->AsWeakPtr(),
135 disk,
136 UPDATE_DEVICE_ADDED);
137 }
138
139 // static
140 void RemovableDeviceNotificationsMac::DiskDisappearedCallback(
141 DADiskRef disk,
142 void* context) {
143 RemovableDeviceNotificationsMac* notifications =
144 static_cast<RemovableDeviceNotificationsMac*>(context);
145 GetDiskInfoAndUpdate(notifications->AsWeakPtr(),
146 disk,
147 UPDATE_DEVICE_REMOVED);
148 }
149
150 // static
151 void RemovableDeviceNotificationsMac::DiskDescriptionChangedCallback(
152 DADiskRef disk,
153 CFArrayRef keys,
154 void *context) {
155 RemovableDeviceNotificationsMac* notifications =
156 static_cast<RemovableDeviceNotificationsMac*>(context);
157 GetDiskInfoAndUpdate(notifications->AsWeakPtr(),
158 disk,
159 UPDATE_DEVICE_CHANGED);
160 }
161
162 bool RemovableDeviceNotificationsMac::ShouldPostNotificationForDisk(
163 const DiskInfoMac& info) const {
164 // Only post notifications about disks that have no empty fields and
165 // are removable.
166 return !info.bsd_name().empty() &&
167 !info.device_id().empty() &&
168 !info.display_name().empty() &&
169 !info.mount_point().empty() &&
170 (info.type() == MediaStorageUtil::REMOVABLE_MASS_STORAGE_WITH_DCIM ||
171 info.type() == MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM);
172 }
173
174 bool RemovableDeviceNotificationsMac::FindDiskWithMountPoint(
175 const FilePath& mount_point,
176 DiskInfoMac* info) const {
177 for (std::map<std::string, DiskInfoMac>::const_iterator
178 it = disk_info_map_.begin(); it != disk_info_map_.end(); ++it) {
179 if (it->second.mount_point() == mount_point) {
180 *info = it->second;
181 return true;
182 }
183 }
184 return false;
185 }
186
187 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698