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

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 drive status changes.
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;
191 // Delete previous disk info for this path:
192 bool is_new = true;
193 std::string device_path_string(device_path);
194 DiskMap::iterator iter = disks_.find(device_path_string);
195 if (iter != disks_.end()) {
196 delete iter->second;
197 disks_.erase(iter);
198 is_new = false;
199 }
52 std::string path; 200 std::string path;
53 std::string mountpath; 201 std::string mountpath;
54 std::string systempath; 202 std::string systempath;
55 bool parent; 203 if (disk->path() != NULL)
56 bool hasmedia; 204 path = disk->path();
57 if (status.disks[i].path != NULL) { 205
58 path = status.disks[i].path; 206 if (disk->mount_path() != NULL)
59 } 207 mountpath = disk->mount_path();
60 if (status.disks[i].mountpath != NULL) { 208
61 mountpath = status.disks[i].mountpath; 209 if (disk->system_path() != NULL)
62 } 210 systempath = disk->system_path();
63 if (status.disks[i].systempath != NULL) { 211
64 systempath = status.disks[i].systempath; 212 Disk* new_disk = new Disk(path,
65 } 213 mountpath,
66 parent = status.disks[i].isparent; 214 systempath,
67 hasmedia = status.disks[i].hasmedia; 215 disk->is_drive(),
68 disks_.push_back(Disk(path, 216 disk->has_media(),
69 mountpath, 217 disk->on_boot_device());
70 systempath, 218 disks_.insert(
71 parent, 219 std::pair<std::string, Disk*>(device_path_string, new_disk));
72 hasmedia)); 220 FireDiskStatusUpdate(is_new ? MOUNT_DISK_ADDED : MOUNT_DISK_CHANGED,
73 } 221 new_disk);
74 } 222 } else {
75 223 LOG(WARNING) << "Property retrieval request failed for device "
76 static void MountStatusChangedHandler(void* object, 224 << device_path << ", with error: "
77 const MountStatus& status, 225 << (error_message ? error_message : "Unknown");
78 MountEventType evt, 226 }
79 const char* path) { 227 }
80 MountLibraryImpl* mount = static_cast<MountLibraryImpl*>(object); 228
81 std::string devicepath = path; 229 void OnRequestMountInfo(const char** devices,
82 mount->ParseDisks(status); 230 size_t devices_len,
83 mount->UpdateMountStatus(status, evt, devicepath); 231 MountMethodErrorType error,
232 const char* error_message) {
233 std::set<std::string> current_device_set;
234 if (error == MOUNT_METHOD_ERROR_NONE && devices && devices_len) {
235 // Initiate properties fetch for all removable disks,
236 bool found_disk = false;
237 for (size_t i = 0; i < devices_len; i++) {
238 if (!devices[i]) {
239 NOTREACHED();
240 continue;
241 }
242 current_device_set.insert(std::string(devices[i]));
243 found_disk = true;
244 // Initiate disk property retrieval for each relevant device path.
245 GetDiskProperties(devices[i],
246 &MountLibraryImpl::GetDiskPropertiesCallback,
247 this);
248 }
249 } else if (error != MOUNT_METHOD_ERROR_NONE) {
250 LOG(WARNING) << "Request mount info retrieval request failed with error: "
251 << (error_message ? error_message : "Unknown");
252 }
253 // Search and remove disks that are no longer present.
254 for (MountLibrary::DiskMap::iterator iter = disks_.begin();
255 iter != disks_.end(); ) {
256 if (current_device_set.find(iter->first) == current_device_set.end()) {
257 Disk* disk = iter->second;
258 FireDiskStatusUpdate(MOUNT_DISK_REMOVED, disk);
259 delete iter->second;
260 disks_.erase(iter++);
261 } else {
262 ++iter;
263 }
264 }
265 }
266
267 void OnMountEvent(MountEventType evt,
268 const char* device_path) {
269 if (!device_path)
270 return;
271 MountLibraryEventType type;
272 switch (evt) {
273 case DISK_ADDED:
274 case DISK_CHANGED: {
275 GetDiskProperties(device_path,
276 &MountLibraryImpl::GetDiskPropertiesCallback,
277 this);
278 return;
279 }
280 case DISK_REMOVED: {
281 // Search and remove disks that are no longer present.
282 MountLibrary::DiskMap::iterator iter =
283 disks_.find(std::string(device_path));
284 if (iter != disks_.end()) {
285 Disk* disk = iter->second;
286 FireDiskStatusUpdate(MOUNT_DISK_REMOVED, disk);
287 delete iter->second;
288 disks_.erase(iter);
289 }
290 return;
291 }
292 case DEVICE_ADDED: {
293 type = MOUNT_DEVICE_ADDED;
294 break;
295 }
296 case DEVICE_REMOVED: {
297 type = MOUNT_DEVICE_REMOVED;
298 break;
299 }
300 case DEVICE_SCANNED: {
301 type = MOUNT_DEVICE_SCANNED;
302 break;
303 }
304 }
305 FireDeviceStatusUpdate(type, std::string(device_path));
84 } 306 }
85 307
86 void Init() { 308 void Init() {
87 // Getting the monitor status so that the daemon starts up. 309 // Getting the monitor status so that the daemon starts up.
88 MountStatus* mount = RetrieveMountInformation(); 310 mount_status_connection_ = MonitorMountEvents(
89 if (!mount) { 311 &MonitorMountEventsHandler, this);
90 LOG(ERROR) << "Failed to retrieve mount information"; 312 }
91 return; 313
92 } 314 void FireDiskStatusUpdate(MountLibraryEventType evt,
93 ParseDisks(*mount); 315 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. 316 // Make sure we run on UI thread.
104 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 317 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
105
106 FOR_EACH_OBSERVER( 318 FOR_EACH_OBSERVER(
107 Observer, observers_, MountChanged(this, evt, path)); 319 Observer, observers_, DiskChanged(evt, disk));
108 } 320 }
321
322 void FireDeviceStatusUpdate(MountLibraryEventType evt,
323 const std::string& device_path) {
324 // Make sure we run on UI thread.
325 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
326 FOR_EACH_OBSERVER(
327 Observer, observers_, DeviceChanged(evt, device_path));
328 }
329
330 // Mount event change observers.
109 ObserverList<Observer> observers_; 331 ObserverList<Observer> observers_;
110 332
111 // A reference to the mount api, to allow callbacks when the mount 333 // A reference to the mount api, to allow callbacks when the mount
112 // status changes. 334 // status changes.
113 MountStatusConnection mount_status_connection_; 335 MountEventConnection mount_status_connection_;
114 336
115 // The list of disks found. 337 // The list of disks found.
116 DiskVector disks_; 338 MountLibrary::DiskMap disks_;
117 339
118 DISALLOW_COPY_AND_ASSIGN(MountLibraryImpl); 340 DISALLOW_COPY_AND_ASSIGN(MountLibraryImpl);
119 }; 341 };
120 342
121 class MountLibraryStubImpl : public MountLibrary { 343 class MountLibraryStubImpl : public MountLibrary {
122 public: 344 public:
123 MountLibraryStubImpl() {} 345 MountLibraryStubImpl() {}
124 virtual ~MountLibraryStubImpl() {} 346 virtual ~MountLibraryStubImpl() {}
125 347
126 // MountLibrary overrides. 348 // MountLibrary overrides.
127 virtual void AddObserver(Observer* observer) {} 349 virtual void AddObserver(Observer* observer) OVERRIDE {}
128 virtual void RemoveObserver(Observer* observer) {} 350 virtual void RemoveObserver(Observer* observer) OVERRIDE {}
129 virtual const DiskVector& disks() const { return disks_; } 351 virtual const DiskMap& disks() const OVERRIDE { return disks_; }
130 virtual bool MountPath(const char* device_path) { return false; } 352 virtual void RequestMountInfoRefresh() OVERRIDE {}
131 virtual bool IsBootPath(const char* device_path) { return true; } 353 virtual void MountPath(const char* device_path) OVERRIDE {}
354 virtual void UnmountPath(const char* device_path) OVERRIDE {}
355 virtual bool IsBootPath(const char* device_path) OVERRIDE { return true; }
132 356
133 private: 357 private:
134 // The list of disks found. 358 // The list of disks found.
135 DiskVector disks_; 359 DiskMap disks_;
136 360
137 DISALLOW_COPY_AND_ASSIGN(MountLibraryStubImpl); 361 DISALLOW_COPY_AND_ASSIGN(MountLibraryStubImpl);
138 }; 362 };
139 363
140 // static 364 // static
141 MountLibrary* MountLibrary::GetImpl(bool stub) { 365 MountLibrary* MountLibrary::GetImpl(bool stub) {
142 if (stub) 366 if (stub)
143 return new MountLibraryStubImpl(); 367 return new MountLibraryStubImpl();
144 else 368 else
145 return new MountLibraryImpl(); 369 return new MountLibraryImpl();
146 } 370 }
147 371
148 } // namespace chromeos 372 } // namespace chromeos
149 373
150 // Allows InvokeLater without adding refcounting. This class is a Singleton and 374 // Allows InvokeLater without adding refcounting. This class is a Singleton and
151 // won't be deleted until it's last InvokeLater is run. 375 // won't be deleted until it's last InvokeLater is run.
152 DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::MountLibraryImpl); 376 DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::MountLibraryImpl);
153 377
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698