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

Side by Side Diff: chrome/browser/chromeos/cros/mount_library.cc

Issue 6674043: Rewritten MountLibrary to work with non-blocking mount API calls in libcros.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 9 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
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/cros/mount_library.h" 5 #include "chrome/browser/chromeos/cros/mount_library.h"
6 6
7 #include <set>
8
7 #include "base/message_loop.h" 9 #include "base/message_loop.h"
8 #include "base/string_util.h" 10 #include "base/string_util.h"
9 #include "chrome/browser/chromeos/cros/cros_library.h" 11 #include "chrome/browser/chromeos/cros/cros_library.h"
10 #include "content/browser/browser_thread.h" 12 #include "content/browser/browser_thread.h"
11 13
12 namespace chromeos { 14 namespace chromeos {
13 15
14 class MountLibraryImpl : public MountLibrary { 16 class MountLibraryImpl : public MountLibrary {
15 public: 17 public:
16 MountLibraryImpl() : mount_status_connection_(NULL) { 18 MountLibraryImpl() : mount_status_connection_(NULL) {
17 if (CrosLibrary::Get()->EnsureLoaded()) { 19 if (CrosLibrary::Get()->EnsureLoaded())
18 Init(); 20 Init();
21 else
22 LOG(ERROR) << "Cros Library has not been loaded";
23 }
24
25 virtual ~MountLibraryImpl() {
26 if (mount_status_connection_)
27 DisconnectMountEventMonitor(mount_status_connection_);
28 }
29
30 // MountLibrary overrides.
31 virtual void AddObserver(Observer* observer) OVERRIDE {
32 observers_.AddObserver(observer);
33 }
34
35 virtual void RemoveObserver(Observer* observer) OVERRIDE {
36 observers_.RemoveObserver(observer);
37 }
38
39 virtual void MountPath(const char* device_path) OVERRIDE {
40 MountRemovableDevice(device_path,
41 &MountLibraryImpl::MountRemovableDeviceCallback,
42 this);
43 }
44
45 virtual void UnmountPath(const char* device_path) OVERRIDE {
46 UnmountRemovableDevice(device_path,
47 &MountLibraryImpl::UnmountRemovableDeviceCallback,
48 this);
49 }
50
51 virtual void RequestMountInfoRefresh() OVERRIDE {
52 RequestMountInfo(&MountLibraryImpl::RequestMountInfoCallback,
53 this);
54 }
55
56 virtual void RefreshDiskProperties(const Disk* disk) OVERRIDE {
57 DCHECK(disk);
58 GetDiskProperties(disk->device_path().c_str(),
59 &MountLibraryImpl::GetDiskPropertiesCallback,
60 this);
61 }
62
63 const DiskMap& disks() const OVERRIDE { return disks_; }
64
65 private:
66
67 // Callback for MountRemovableDevice method.
68 static void MountRemovableDeviceCallback(void* object,
69 const char* device_path,
70 const char* mount_path,
71 MountMethodErrorType error,
72 const char* error_message) {
73 DCHECK(object);
74 MountLibraryImpl* self = static_cast<MountLibraryImpl*>(object);
75 self->OnMountRemovableDevice(device_path,
76 mount_path,
77 error,
78 error_message);
79 }
80
81 // Callback for UnmountRemovableDevice method.
82 static void UnmountRemovableDeviceCallback(void* object,
83 const char* device_path,
84 const char* mount_path,
85 MountMethodErrorType error,
86 const char* error_message) {
87 DCHECK(object);
88 MountLibraryImpl* self = static_cast<MountLibraryImpl*>(object);
89 self->OnUnmountRemovableDevice(device_path,
90 error,
91 error_message);
92 }
93
94 // Callback for disk information retrieval calls.
95 static void GetDiskPropertiesCallback(void* object,
96 const char* device_path,
97 const DiskInfo* disk,
98 MountMethodErrorType error,
99 const char* error_message) {
100 DCHECK(object);
101 MountLibraryImpl* self = static_cast<MountLibraryImpl*>(object);
102 self->OnGetDiskProperties(device_path,
103 disk,
104 error,
105 error_message);
106 }
107
108 // Callback for RequestMountInfo call.
109 static void RequestMountInfoCallback(void* object,
110 const char** devices,
111 size_t device_len,
112 MountMethodErrorType error,
113 const char* error_message) {
114 DCHECK(object);
115 MountLibraryImpl* self = static_cast<MountLibraryImpl*>(object);
116 self->OnRequestMountInfo(devices,
117 device_len,
118 error,
119 error_message);
120 }
121
122 // This method will receive events that are caused by
stevenjb 2011/03/16 22:52:55 partial comment
zel 2011/03/17 01:00:30 Done.
123 static void MonitorMountEventsHandler(void* object,
124 MountEventType evt,
125 const char* device_path) {
126 DCHECK(object);
127 MountLibraryImpl* self = static_cast<MountLibraryImpl*>(object);
128 self->OnMountEvent(evt, device_path);
129 }
130
131
132 void OnMountRemovableDevice(const char* device_path,
133 const char* mount_path,
134 MountMethodErrorType error,
135 const char* error_message) {
136 DCHECK(device_path);
137 DCHECK(mount_path);
138 if (error == MOUNT_METHOD_ERROR_NONE && device_path && mount_path) {
139 std::string path(device_path);
140 DiskMap::iterator iter = disks_.find(path);
141 if (iter == disks_.end()) {
142 // disk might have been removed by now?
143 return;
144 }
145 Disk* disk = iter->second;
146 DCHECK(disk);
147 disk->set_mount_path(mount_path);
148 FireDiskStatusUpdate(MOUNT_DISK_MOUNTED, disk);
19 } else { 149 } else {
20 LOG(ERROR) << "Cros Library has not been loaded"; 150 LOG(WARNING) << "Mount request failed for device "
21 } 151 << device_path << ", with error: "
22 } 152 << (error_message ? error_message : "Unknown");
23 153 }
24 ~MountLibraryImpl() { 154 }
25 if (mount_status_connection_) { 155
26 DisconnectMountStatus(mount_status_connection_); 156 void OnUnmountRemovableDevice(const char* device_path,
27 } 157 MountMethodErrorType error,
28 } 158 const char* error_message) {
29 159 DCHECK(device_path);
30 void AddObserver(Observer* observer) { 160 if (error == MOUNT_METHOD_ERROR_NONE && device_path) {
31 observers_.AddObserver(observer); 161 std::string path(device_path);
32 } 162 DiskMap::iterator iter = disks_.find(path);
33 163 if (iter == disks_.end()) {
34 void RemoveObserver(Observer* observer) { 164 // disk might have been removed by now?
35 observers_.RemoveObserver(observer); 165 return;
36 } 166 }
37 167 Disk* disk = iter->second;
38 bool MountPath(const char* device_path) { 168 DCHECK(disk);
39 return MountDevicePath(device_path); 169 disk->clear_mount_path();
40 } 170 FireDiskStatusUpdate(MOUNT_DISK_UNMOUNTED, disk);
41 171 } else {
42 bool IsBootPath(const char* device_path) { 172 LOG(WARNING) << "Unmount request failed for device "
43 return IsBootDevicePath(device_path); 173 << device_path << ", with error: "
44 } 174 << (error_message ? error_message : "Unknown");
45 175 }
46 const DiskVector& disks() const { return disks_; } 176 }
47 177
48 private: 178 void OnGetDiskProperties(const char* device_path,
49 void ParseDisks(const MountStatus& status) { 179 const DiskInfo* disk,
50 disks_.clear(); 180 MountMethodErrorType error,
51 for (int i = 0; i < status.size; i++) { 181 const char* error_message) {
182 DCHECK(device_path);
183 if (error == MOUNT_METHOD_ERROR_NONE && device_path) {
184 // TODO(zelidrag): Find a better way to filter these out before we
185 // fetch the properties:
186 // Ignore disks coming from the device we booted the system from.
187 if (disk->on_boot_device())
188 return;
189
190 LOG(WARNING) << "Found disk " << device_path;
stevenjb 2011/03/16 22:52:55 -> VLOG(1)
191 // Delete previous disk info for this path:
192 bool is_new = true;
193 DiskMap::iterator iter = disks_.find(std::string(device_path));
194 if (iter != disks_.end()) {
195 delete iter->second;
196 disks_.erase(iter);
197 is_new = false;
198 }
52 std::string path; 199 std::string path;
53 std::string mountpath; 200 std::string mountpath;
54 std::string systempath; 201 std::string systempath;
55 bool parent; 202 if (disk->path() != NULL) {
56 bool hasmedia; 203 path = disk->path();
57 if (status.disks[i].path != NULL) { 204 }
stevenjb 2011/03/16 22:52:55 nit: { } not needed
zel 2011/03/17 01:00:30 Done.
58 path = status.disks[i].path; 205 if (disk->mount_path() != NULL) {
59 } 206 mountpath = disk->mount_path();
60 if (status.disks[i].mountpath != NULL) { 207 }
stevenjb 2011/03/16 22:52:55 nit: { } not needed
zel 2011/03/17 01:00:30 Done.
61 mountpath = status.disks[i].mountpath; 208 if (disk->system_path() != NULL) {
62 } 209 systempath = disk->system_path();
63 if (status.disks[i].systempath != NULL) { 210 }
stevenjb 2011/03/16 22:52:55 nit: { } not needed
zel 2011/03/17 01:00:30 Done.
64 systempath = status.disks[i].systempath; 211 Disk* new_disk = new Disk(path,
65 } 212 mountpath,
66 parent = status.disks[i].isparent; 213 systempath,
67 hasmedia = status.disks[i].hasmedia; 214 disk->is_drive(),
68 disks_.push_back(Disk(path, 215 disk->has_media(),
69 mountpath, 216 disk->on_boot_device());
stevenjb 2011/03/16 22:52:55 Is it valid for a Disk to have any empty path, mou
zel 2011/03/17 01:00:30 Yes, mount path can be empty. We actually kick off
70 systempath, 217 disks_.insert(
71 parent, 218 std::pair<std::string, Disk*>(std::string(device_path), new_disk));
stevenjb 2011/03/16 22:52:55 nit: second std::string conversion of device_path
zel 2011/03/17 01:00:30 Done.
72 hasmedia)); 219 FireDiskStatusUpdate(is_new ? MOUNT_DISK_ADDED : MOUNT_DISK_CHANGED,
73 } 220 new_disk);
74 } 221 } else {
75 222 LOG(WARNING) << "Property retrieval request failed for device "
76 static void MountStatusChangedHandler(void* object, 223 << device_path << ", with error: "
77 const MountStatus& status, 224 << (error_message ? error_message : "Unknown");
78 MountEventType evt, 225 }
79 const char* path) { 226 }
80 MountLibraryImpl* mount = static_cast<MountLibraryImpl*>(object); 227
81 std::string devicepath = path; 228 void OnRequestMountInfo(const char** devices,
82 mount->ParseDisks(status); 229 size_t device_len,
stevenjb 2011/03/16 22:52:55 nit: devices_len
zel 2011/03/17 01:00:30 Done.
83 mount->UpdateMountStatus(status, evt, devicepath); 230 MountMethodErrorType error,
231 const char* error_message) {
232 std::set<std::string> current_device_set;
233 if (error == MOUNT_METHOD_ERROR_NONE && devices && device_len) {
234 // Initiate properties fetch for all removable disks,
235 bool found_disk = false;
236 for (size_t i = 0; i < device_len; i++) {
stevenjb 2011/03/16 22:52:55 DCHECK(devices[i]) or if (!devices[i]) continue;
zel 2011/03/17 01:00:30 Done.
237 current_device_set.insert(std::string(devices[i]));
238 found_disk = true;
239 // Initiate disk property retrieval for each relevant device path.
240 GetDiskProperties(devices[i],
241 &MountLibraryImpl::GetDiskPropertiesCallback,
242 this);
243 }
244 } else if (error != MOUNT_METHOD_ERROR_NONE) {
245 LOG(WARNING) << "Request mount info retrieval request failed with error: "
246 << (error_message ? error_message : "Unknown");
247 }
248 // Search and remove disks that are no longer present.
249 for (MountLibrary::DiskMap::iterator iter = disks_.begin();
250 iter != disks_.end();
251 ++iter) {
stevenjb 2011/03/16 22:52:55 ++iter here and erase(iter++) below; remove this a
zel 2011/03/17 01:00:30 Good catch. Done.
252 if (current_device_set.find(iter->first) == current_device_set.end()) {
253 Disk* disk = iter->second;
254 FireDiskStatusUpdate(MOUNT_DISK_REMOVED, disk);
255 delete iter->second;
256 disks_.erase(iter++);
257 }
258 }
259 }
260
261 void OnMountEvent(MountEventType evt,
262 const char* device_path) {
263 if (!device_path)
264 return;
265 MountLibraryEventType type;
266 switch (evt) {
267 case DISK_ADDED:
268 case DISK_CHANGED: {
269 GetDiskProperties(device_path,
270 &MountLibraryImpl::GetDiskPropertiesCallback,
271 this);
272 return;
273 }
274 case DISK_REMOVED: {
275 // Search and remove disks that are no longer present.
276 MountLibrary::DiskMap::iterator iter =
277 disks_.find(std::string(device_path));
278 if (iter != disks_.end()) {
279 Disk* disk = iter->second;
280 FireDiskStatusUpdate(MOUNT_DISK_REMOVED, disk);
281 delete iter->second;
282 disks_.erase(iter++);
stevenjb 2011/03/16 22:52:55 ++ unnecessary
zel 2011/03/17 01:00:30 Done.
283 }
284 return;
285 }
286 case DEVICE_ADDED: {
287 type = MOUNT_DEVICE_ADDED;
288 break;
289 }
290 case DEVICE_REMOVED: {
291 type = MOUNT_DEVICE_REMOVED;
292 break;
293 }
294 case DEVICE_SCANNED: {
295 type = MOUNT_DEVICE_SCANNED;
296 break;
297 }
298 }
299 FireDeviceStatusUpdate(type, std::string(device_path));
84 } 300 }
85 301
86 void Init() { 302 void Init() {
87 // Getting the monitor status so that the daemon starts up. 303 // Getting the monitor status so that the daemon starts up.
88 MountStatus* mount = RetrieveMountInformation(); 304 mount_status_connection_ = MonitorMountEvents(
89 if (!mount) { 305 &MonitorMountEventsHandler, this);
90 LOG(ERROR) << "Failed to retrieve mount information"; 306 }
91 return; 307
92 } 308 void FireDiskStatusUpdate(MountLibraryEventType evt,
93 ParseDisks(*mount); 309 const Disk* disk) {
94 FreeMountStatus(mount);
95
96 mount_status_connection_ = MonitorMountStatus(
97 &MountStatusChangedHandler, this);
98 }
99
100 void UpdateMountStatus(const MountStatus& status,
101 MountEventType evt,
102 const std::string& path) {
103 // Make sure we run on UI thread. 310 // Make sure we run on UI thread.
104 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
105
106 FOR_EACH_OBSERVER( 312 FOR_EACH_OBSERVER(
107 Observer, observers_, MountChanged(this, evt, path)); 313 Observer, observers_, DiskChanged(evt, disk));
108 } 314 }
315
316 void FireDeviceStatusUpdate(MountLibraryEventType evt,
317 const std::string& device_path) {
318 // Make sure we run on UI thread.
319 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
320 FOR_EACH_OBSERVER(
321 Observer, observers_, DeviceChanged(evt, device_path));
322 }
323
324 // Mount event change observers.
109 ObserverList<Observer> observers_; 325 ObserverList<Observer> observers_;
110 326
111 // A reference to the mount api, to allow callbacks when the mount 327 // A reference to the mount api, to allow callbacks when the mount
112 // status changes. 328 // status changes.
113 MountStatusConnection mount_status_connection_; 329 MountEventConnection mount_status_connection_;
114 330
115 // The list of disks found. 331 // The list of disks found.
116 DiskVector disks_; 332 MountLibrary::DiskMap disks_;
117 333
118 DISALLOW_COPY_AND_ASSIGN(MountLibraryImpl); 334 DISALLOW_COPY_AND_ASSIGN(MountLibraryImpl);
119 }; 335 };
120 336
121 class MountLibraryStubImpl : public MountLibrary { 337 class MountLibraryStubImpl : public MountLibrary {
122 public: 338 public:
123 MountLibraryStubImpl() {} 339 MountLibraryStubImpl() {}
124 virtual ~MountLibraryStubImpl() {} 340 virtual ~MountLibraryStubImpl() {}
125 341
126 // MountLibrary overrides. 342 // MountLibrary overrides.
127 virtual void AddObserver(Observer* observer) {} 343 virtual void AddObserver(Observer* observer) OVERRIDE {}
128 virtual void RemoveObserver(Observer* observer) {} 344 virtual void RemoveObserver(Observer* observer) OVERRIDE {}
129 virtual const DiskVector& disks() const { return disks_; } 345 virtual const DiskMap& disks() const OVERRIDE { return disks_; }
130 virtual bool MountPath(const char* device_path) { return false; } 346 virtual void RequestMountInfoRefresh() OVERRIDE {}
131 virtual bool IsBootPath(const char* device_path) { return true; } 347 virtual void MountPath(const char* device_path) OVERRIDE {}
348 virtual void UnmountPath(const char* device_path) OVERRIDE {}
349 virtual bool IsBootPath(const char* device_path) OVERRIDE { return true; }
132 350
133 private: 351 private:
134 // The list of disks found. 352 // The list of disks found.
135 DiskVector disks_; 353 DiskMap disks_;
136 354
137 DISALLOW_COPY_AND_ASSIGN(MountLibraryStubImpl); 355 DISALLOW_COPY_AND_ASSIGN(MountLibraryStubImpl);
138 }; 356 };
139 357
140 // static 358 // static
141 MountLibrary* MountLibrary::GetImpl(bool stub) { 359 MountLibrary* MountLibrary::GetImpl(bool stub) {
142 if (stub) 360 if (stub)
143 return new MountLibraryStubImpl(); 361 return new MountLibraryStubImpl();
144 else 362 else
145 return new MountLibraryImpl(); 363 return new MountLibraryImpl();
146 } 364 }
147 365
148 } // namespace chromeos 366 } // namespace chromeos
149 367
150 // Allows InvokeLater without adding refcounting. This class is a Singleton and 368 // Allows InvokeLater without adding refcounting. This class is a Singleton and
151 // won't be deleted until it's last InvokeLater is run. 369 // won't be deleted until it's last InvokeLater is run.
152 DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::MountLibraryImpl); 370 DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::MountLibraryImpl);
153 371
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698