OLD | NEW |
---|---|
(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 /** | |
6 * FileManager constructor. | |
rginda
2012/05/15 19:51:15
Copypasta documentation here. And the rest of the
SeRya
2012/05/16 13:45:44
Robert, I uploaded this CL for preliminary code re
| |
7 * | |
8 * FileManager objects encapsulate the functionality of the file selector | |
9 * dialogs, as well as the full screen file manager application (though the | |
10 * latter is not yet implemented). | |
11 * | |
12 * @constructor | |
13 * @param {HTMLElement} dialogDom The DOM node containing the prototypical | |
14 * dialog UI. | |
15 */ | |
16 function VolumeManager() { | |
17 // The list of archives requested to mount. We will show contents once | |
18 // archive is mounted, but only for mounts from within this filebrowser tab. | |
19 this.requests_ = {}; | |
20 this.mountedVolumes_ = {}; | |
21 | |
22 this.initMountPoints_(); | |
23 chrome.fileBrowserPrivate.onMountCompleted.addListener( | |
24 this.onMountCompleted_.bind(this)); | |
25 this.gDataStatus_ = VolumeManager.GDataStatus.UNMOUNTED; | |
26 } | |
27 | |
28 VolumeManager.prototype.__proto__ = cr.EventTarget.prototype; | |
29 | |
30 VolumeManager.Error = { | |
31 /* Internal errors */ | |
32 NOT_MOUNTED: 'not_mounted', | |
33 TIMEOUT: 'timeout', | |
34 | |
35 /* System events */ | |
36 UNKNOWN: 'error_unknown', | |
37 INTERNAL: 'error_internal', | |
38 UNKNOWN_FILESYSTEM: 'error_unknown_filesystem', | |
39 UNSUPPORTED_FILESYSTEM: 'error_unsuported_filesystem', | |
40 INVALID_ARCHIVE: 'error_invalid_archive', | |
41 LIBCROS_MISSING: 'error_libcros_missing', | |
42 AUTHENTICATION: 'error_authentication', | |
43 PATH_UNMOUNTED: 'error_path_unmounted' | |
44 }; | |
45 | |
46 VolumeManager.GDataStatus = { | |
47 UNMOUNTED: 'unmounted', | |
48 MOUNTING: 'mounting', | |
49 ERROR: 'error', | |
50 MOUNTED: 'mounted' | |
51 }; | |
52 | |
53 VolumeManager.TIMEOUT = 15 * 60 * 1000; | |
54 VolumeManager.MOUNTING_DELAY = 500; | |
55 | |
56 VolumeManager.getInstance = function() { | |
57 return VolumeManager.instance_ = VolumeManager.instance_ || new VolumeManager( ); | |
dgozman
2012/05/16 14:31:46
long line
| |
58 }; | |
59 | |
60 VolumeManager.prototype.setGDataStatus_ = function(newStatus) { | |
61 if (this.gDataStatus_ != newStatus) { | |
62 this.gDataStatus_ = newStatus; | |
63 cr.dispatchSimpleEvent(this, 'gdata-status-changed'); | |
64 } | |
65 }; | |
66 | |
67 VolumeManager.prototype.getGDataStatus = function() { | |
68 return this.gDataStatus_; | |
69 }; | |
70 | |
71 VolumeManager.prototype.isMounted = function(mountPath) { | |
72 return mountPath in this.mountedVolumes_; | |
73 }; | |
74 | |
75 VolumeManager.prototype.initMountPoints_ = function() { | |
76 var mountedVolumes = []; | |
77 var self = this; | |
78 var index = 0; | |
79 function step(mountPoints) { | |
80 if (index < mountPoints.length) { | |
81 var info = mountPoints[index]; | |
82 if (info.mountType == 'gdata') | |
83 console.error('GData is not extpected initially mounted'); | |
84 self.makeVolumeInfo_('/' + info.mountPath, info.mountCondition, | |
85 function(volume) { | |
86 mountedVolumes.push(volume); | |
87 index++; | |
88 step(mountPoints); | |
89 }); | |
90 } else { | |
91 for (var i = 0; i < mountedVolumes.length; i++) { | |
92 var volume = mountedVolumes[i]; | |
93 self.mountedVolumes_[volume.mountPath] = volume; | |
94 } | |
95 if (mountedVolumes.length > 0) | |
96 self.notifyChange_(); | |
97 } | |
98 } | |
99 | |
100 chrome.fileBrowserPrivate.getMountPoints(step); | |
101 }; | |
102 | |
103 /** | |
104 * Event handler called when some volume was mounted or unmouted. | |
105 */ | |
106 VolumeManager.prototype.onMountCompleted_ = function(event) { | |
107 if (event.eventType == 'mount') { | |
108 if (event.mountPath) { | |
dgozman
2012/05/16 14:31:46
check event.status == 'success' here?
| |
109 var requestKey = this.makeRequestKey_('mount', event.mountType, event.sour cePath); | |
dgozman
2012/05/16 14:31:46
long line
| |
110 this.makeVolumeInfo_(event.mountPath, event.status, function(volume) { | |
111 this.mountedVolumes_[volume.mountPath] = volume; | |
112 this.finishRequest_(requestKey, event.status, event.mountPath); | |
113 this.notifyChange_(); | |
114 }.bind(this)); | |
115 } else { | |
116 console.log('No mount path'); | |
117 this.finishRequest_(requestKey, event.status); | |
118 } | |
119 } else if (event.eventType == 'unmount') { | |
120 var mountPath = '/' + event.mountPath; | |
121 var status = event.status; | |
122 if (status == VolumeManager.Error.PATH_UNMOUNTED) { | |
123 console.log('Volume already unmounted: ', mountPath); | |
124 status = 'success'; | |
125 } | |
126 this.finishRequest_(this.makeRequestKey_('mount', '', mountPath), status); | |
dgozman
2012/05/16 14:31:46
'mount' -> 'unmount' ?
| |
127 | |
128 if (event.status == 'success') { | |
129 delete this.mountedVolumes_[mountPath]; | |
130 this.notifyChange_(); | |
131 } | |
132 } | |
133 | |
134 if (event.mountType == 'gdata') { | |
135 if (event.status == 'success') { | |
136 if (event.eventType == 'mount') | |
137 this.setGDataStatus_(VolumeManager.GDataStatus.MOUNTED); | |
138 else if (event.eventType == 'unmount' && event.status == 'success') | |
dgozman
2012/05/16 14:31:46
event.status == 'success' two lines above
| |
139 this.setGDataStatus_(VolumeManager.GDataStatus.UMOUNTED); | |
140 } | |
141 } | |
142 }; | |
143 | |
144 VolumeManager.prototype.makeVolumeInfo_ = function( | |
145 mountPath, status, callback) { | |
146 chrome.fileBrowserPrivate.getVolumeMetadata(this.makeUrl_(mountPath), | |
147 function(metadata) { | |
148 callback({ | |
149 mountPath: mountPath, | |
150 status: status, | |
151 readonly: !!metadata && metadata.isReadOnly | |
152 }); | |
153 }.bind(this)); | |
154 }; | |
155 | |
156 /** | |
157 * @param {string} requestType 'mount' | 'unmount' | |
158 * @param {string} mountType 'device' | 'file' | 'network' | 'gdata'. | |
159 * @param {string?} opt_sourcePath | |
160 */ | |
161 VolumeManager.prototype.makeRequestKey_ = function(requestType, mountType, opt_m ountPath) { | |
dgozman
2012/05/16 14:31:46
long line
| |
162 return requestType + ':' + mountType + ':' + (opt_mountPath || ''); | |
163 }; | |
164 | |
165 VolumeManager.prototype.mountGData = function(successCallback, errorCallback) { | |
166 if (this.getGDataStatus() == VolumeManager.GDataStatus.ERROR) { | |
167 this.setGDataStatus_(VolumeManager.GDataStatus.UNMOUNTED); | |
168 } | |
169 var self = this; | |
170 var timeout = setTimeout(function() { | |
171 if (self.getGDataStatus() == VolumeManager.GDataStatus.UNMOUNTED) | |
172 self.setGDataStatus_(VolumeManager.GDataStatus.MOUNTING); | |
173 timeout = null; | |
174 }, VolumeManager.MOUNTING_DELAY); | |
175 this.mount_('', 'gdata', function(mountPath) { | |
176 if (timeout !== null) | |
177 clearTimeout(timeout); | |
178 successCallback(mountPath); | |
179 }, function(error) { | |
180 if (self.getGDataStatus() != VolumeManager.GDataStatus.MOUNTED) | |
181 self.setGDataStatus_(VolumeManager.GDataStatus.ERROR); | |
182 if (timeout != null) | |
183 clearTimeout(timeout); | |
184 errorCallback(error); | |
185 }); | |
186 }; | |
187 | |
188 VolumeManager.prototype.getMountCondition = function(mountPath) { | |
dgozman
2012/05/16 14:31:46
I'd suggest to rename this to getMountStatus.
| |
189 return this.getVolumeInfo_(mountPath).status; | |
190 }; | |
191 | |
192 VolumeManager.prototype.isReadOnly = function(mountPath) { | |
193 return this.getVolumeInfo_(mountPath).readonly; | |
194 }; | |
195 | |
196 VolumeManager.prototype.getVolumeInfo_ = function(mountPath) { | |
197 return this.mountedVolumes_[mountPath] || {}; | |
198 }; | |
199 | |
200 /** | |
201 * Unmounts device. | |
dgozman
2012/05/16 14:31:46
indentation
| |
202 * @param {Entry} entry The entry to unmount. | |
203 */ | |
204 VolumeManager.prototype.unmount = function(mountPath, successCallback, errorCall back) { | |
dgozman
2012/05/16 14:31:46
long line
| |
205 var volumeInfo = this.mountedVolumes_[mountPath]; | |
206 if (!volumeInfo) { | |
207 errorCallback(VolumeManager.Error.NOT_NOUNTED); | |
208 return; | |
209 } | |
210 | |
211 chrome.fileBrowserPrivate.removeMount(this.makeUrl_(mountPath)); | |
212 this.startRequest_(this.makeRequestKey_('unmount', '', mountPath)); | |
213 }; | |
214 | |
215 VolumeManager.prototype.mountArchive = function(fullPath, successCallback, | |
216 errorCallback) { | |
217 var requestKey = this.makeRequestKey_('mount', 'file'); | |
218 if (requestKey in this.requests_) { | |
219 // Parallel requests are not supported. API doesn't provide a way | |
220 // to find request for specific response. | |
221 errorCallback('inprogress'); | |
222 return; | |
223 } | |
224 this.mount_(this.makeUrl_(fullPath), | |
225 'file', successCallback, errorCallback); | |
226 }; | |
227 | |
228 VolumeManager.prototype.makeUrl_ = function(path) { | |
dgozman
2012/05/16 14:31:46
Move this method to util.js.
| |
229 return 'filesystem:' + chrome.extension.getURL('external' + path); | |
230 }; | |
231 | |
232 VolumeManager.prototype.mount_ = function(url, mountType, | |
233 successCallback, errorCallback) { | |
234 chrome.fileBrowserPrivate.addMount(url, mountType, {}, | |
235 function(sourcePath) { | |
236 var requestKey = this.makeRequestKey_('mount', mountType, sourcePath); | |
237 this.startRequest_(requestKey, successCallback, errorCallback); | |
238 }.bind(this)); | |
239 }; | |
240 | |
241 VolumeManager.prototype.startRequest_ = function(key, | |
242 successCallback, errorCallback) { | |
243 if (key in this.requests_) { | |
244 var request = this.requests_[key]; | |
245 request.successCallbacks.push(successCallback); | |
246 request.errorCallbacks.push(errorCallback); | |
247 } else { | |
248 this.requests_[key] = { | |
249 successCallbacks: [successCallback], | |
250 errorCallbacks: [errorCallback], | |
251 | |
252 timeout: setTimeout(this.onTimeout_.bind(this, key), | |
253 VolumeManager.TIMEOUT) | |
254 }; | |
255 } | |
256 }; | |
257 | |
258 VolumeManager.prototype.onTimeout_ = function(key) { | |
259 this.invokeRequestCallbacks_(this.requests_[key], | |
260 VolumeManager.Error.TIMEOUT); | |
261 delete this.requests_[key]; | |
262 }; | |
263 | |
264 VolumeManager.prototype.finishRequest_ = function(key, status, opt_mountPath) { | |
265 var request = this.requests_[key]; | |
266 if (!request) | |
267 return; | |
268 | |
269 clearTimeout(request.timeout); | |
270 this.invokeRequestCallbacks_(request, status, opt_mountPath); | |
271 delete this.requests_[key]; | |
272 } | |
273 | |
274 VolumeManager.prototype.invokeRequestCallbacks_= function(request, status, | |
275 opt_mountPath) { | |
276 function callEach(callbacks, self, args) { | |
277 for (var i = 0; i < callbacks.length; i++) { | |
278 callbacks[i].apply(self, args); | |
dgozman
2012/05/16 14:31:46
self -> null
| |
279 } | |
280 } | |
281 if (status == 'success') | |
282 callEach(request.successCallbacks, this, [opt_mountPath]); | |
283 else | |
284 callEach(request.errorCallbacks, this, [status]); | |
285 }; | |
286 | |
287 VolumeManager.prototype.notifyChange_ = function() { | |
288 cr.dispatchSimpleEvent(this, 'change'); | |
289 }; | |
290 | |
OLD | NEW |